code wiki / _hdl_build / nx_sites_daemon_v2.nx

nx_sites_daemon_v2.nx source

↩ module page · 1886 lines · 120427 B

1// nx_sites_daemon_v2.nx -- sovereign multi-vhost HTTPS daemon, generation 2. 2// 3// Operator 2026-06-09: "nishi video from the hardware layer up ... hosted 4// again on nishifamily.com/video ... improve anything on the website hosting 5// path to S-class exceed" + "less lag for ukrainians/belarusians" + "record 6// circles like telegram, private/romantic ones auto-archived for review." 7// 8// What changed vs runtime/bin/nx_sites_daemon.nx (v1) and WHY (each is a 9// measured v1 defect, see gates): 10// D1 CHUNKED TLS SEND -- v1's app_send built ONE record for the whole 11// payload; RFC 8446 5.1 caps record plaintext at 16384, so v1 could 12// not serve ANY asset over ~16.3KB (the /video page is 19KB). 13// v2 sends everything through nx_tls13_app_send_fd (gated). 14// D2 RECORD-FRAMED RECEIVE -- v1 assumed one sys_read = one TLS record; 15// v2 reads with nx_tls13_read_record_from_fd and reassembles the 16// request across records until CRLFCRLF (bounded). 17// D3 HOT HOSTING WITH FALLTHROUGH -- v1's hr_serve 404'd on a missing 18// file, so nishifamily.com could not live in sites.conf without 19// killing /wiki. v2 uses hr_serve2: file hit = hot serve (keep-alive, 20// bounds-checked); MISS = fall through to the legacy baked routing. 21// andelinwest keeps REAL 404s (no placeholder bleed). 22// D4 WSS -- /signal/* upgrade requests become a TLS-terminating pump to 23// the loopback N-party signaling daemon (nx_signaling_v2 on 24// 127.0.0.1:8445). wss://nishifamily.com/signal/<room> on :8443 -- 25// no new public port, secure-origin so getUserMedia works (the root 26// cause the old :8282 HTTP video room died). 27// D5 CIRCLES -- POST /video/circle?room=R&from=F&priv=0|1 streams the 28// browser-recorded webm body (record by record) to the circles store; 29// priv=1 -> circles/private (auto-archive for later review), 30// else circles/public. GET /video/circles?room=R lists a room's 31// public circles as JSON; GET /video/circle/<name> plays one back 32// (8MB serve buffer). Storage is OUTSIDE the doc root. 33// 34// Composes (all KAT'd/gated): nx_tls13_* session + record stack, 35// nx_tls13_app_send_fd (gate: 10/10), nx_host_router v2 (gate: 14/14), 36// nx_poll, nx_sites_telemetry, wiki engine handles. 37// license_tier: ORIGINAL 38 39import "nx_syscalls.nx" 40import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host 41import "nx_csprng.nx" 42import "nx_http_server.nx" 43import "nx_tls13_server_session.nx" 44import "nx_tls13_server_session_run.nx" 45import "nx_tls13_server_session_app_data.nx" 46import "nx_tls13_read_record_from_fd.nx" 47import "nx_sites_telemetry.nx" 48import "nx_poll.nx" 49import "wiki/nx_wiki_status.nx" 50import "wiki/nx_wiki_article.nx" 51import "wiki/nx_wiki_queue.nx" 52import "_hdl_build/nx_host_router.nx" 53import "_hdl_build/nx_proxy_route.nx" 54import "_hdl_build/nx_adnet_slot.nx" 55import "_hdl_build/nx_adnet_view.nx" 56import "_hdl_build/nx_adnet_dash.nx" 57import "_hdl_build/nx_adnet_submit.nx" 58import "_hdl_build/nx_tls13_app_send_fd.nx" 59import "_hdl_build/nx_nv1.nx" 60// Route B (SNI-aware TLS, ported from the gated runtime/bin/nx_sites_daemon.nx): peek the 61// cleartext ClientHello SNI, present the matching per-domain wildcard chain. Composes the 62// gated scs_pick_from_clienthello (nx_sites_sni_cert_gate 12/12 unit + 4/4 e2e). 63import "nx_sni_cert_select.nx" 64const NX_MAGIC_8192: i64 = 8192 65const NX_MAGIC_8445: i64 = 8445 66const NX_MAGIC_16000: i64 = 16000 67const NX_MAGIC_65536: i64 = 65536 68const NX_MAGIC_16384: i64 = 16384 69const NX_MAGIC_60000: i64 = 60000 70const NX_MAGIC_51850: i64 = 51850 71const NX_MAGIC_4096: i64 = 4096 72const NX_MAGIC_1048576: i64 = 1048576 73const NX_MAGIC_262144: i64 = 262144 74const NX_MAGIC_131072: i64 = 131072 75const NX_MAGIC_9091: i64 = 9091 76const NX_MAGIC_18190: i64 = 18190 77const NX_MAGIC_18791: i64 = 18791 78const NX_MAGIC_18792: i64 = 18792 79const NX_MAGIC_18794: i64 = 18794 80const NX_MAGIC_18793: i64 = 18793 81const NX_MAGIC_18099: i64 = 18099 82const NX_MAGIC_8791: i64 = 8791 83 84const NX_SD2_PORT: i64 = 8443 85const NX_SD2_BUDGET: i64 = 100000000 86const NX_SD2_MAX_CHILDREN: i64 = 64 87const NX_SD2_CERT_PATH: *u8 = "/volume1/homes/elderwesto/nishihost/certs/le_fullchain.der" as *u8 88const NX_SD2_PRIV_PATH: *u8 = "/volume1/homes/elderwesto/nishihost/certs/le_ecdsa_key.bin" as *u8 89// Route B: per-domain wildcard chains (leaf-first concat-DER + 32-byte P-256 scalar), the SAME 90// files nx_cert_autorenew writes on every renewal (le_<label>_*) -- loading them here RECONNECTS 91// the renewal outputs to the live edge. PAIRED fail-safe: if EITHER file of a pair is absent or 92// malformed, that domain serves the legacy generic pair (never a mismatched cert/key). 93const NX_SD2_CERT_NISHI: *u8 = "/volume1/homes/elderwesto/nishihost/certs/le_nishifamily_fullchain.der" as *u8 94const NX_SD2_PRIV_NISHI: *u8 = "/volume1/homes/elderwesto/nishihost/certs/le_nishifamily_ecdsa_key.bin" as *u8 95const NX_SD2_CERT_ANDELIN: *u8 = "/volume1/homes/elderwesto/nishihost/certs/le_andelinwest_fullchain.der" as *u8 96const NX_SD2_PRIV_ANDELIN: *u8 = "/volume1/homes/elderwesto/nishihost/certs/le_andelinwest_ecdsa_key.bin" as *u8 97// MSG_PEEK (recvfrom flag 0x2): read the cleartext ClientHello WITHOUT consuming it, so the 98// proven handshake re-reads the same bytes -> the SNI peek is invisible to nx_tls13_server_session_run. 99const NX_SD2_MSG_PEEK: i64 = 2 100const NX_SD2_SNI_PEEK_CAP: i64 = 8192 101const NX_SD2_SITES_CONF: *u8 = "/volume1/homes/elderwesto/nishihost/sites.conf" as *u8 102// data-driven PROXY route table (nx_proxy_route): app routes are config rows, no recompile. 103const NX_SD2_PROXY_CONF: *u8 = "/volume1/homes/elderwesto/nishihost/proxy_routes.conf" as *u8 104// data-driven ADNET inventory (universal ad slot; nx_adnet_slot): rows id/advertiser/img/click/ 105// section/weight + @host directives. ABSENT FILE = ads OFF everywhere (kill-switch by construction); 106// a vhost without an @host row NEVER gets a slot (fail-closed). Counters are per-AD only (no visitor 107// id/cookie/IP -- the nx_ad privacy law). Rotation is TIME-based: no per-user frequency state. 108// (docroot-resident so it lands via the EXISTING /api/upload -> /api/promote_content content lane -- 109// zero mgmt-allowlist changes; public-readable is fine: it is the same data every served ad exposes) 110const NX_SD2_ADNET_CONF: *u8 = "/volume1/homes/elderwesto/nishihost/sites/nishifamily/synth/adnet_inventory.txt" as *u8 111const NX_SD2_ADNET_IMPLOG: *u8 = "/volume1/homes/elderwesto/nishihost/adnet_impressions.log" as *u8 112const NX_SD2_ADNET_CLKLOG: *u8 = "/volume1/homes/elderwesto/nishihost/adnet_clicks.log" as *u8 113// served-slot rotation window (us). NAMED code-default tier; store migration = follow-on. 114const NX_SD2_ADNET_ROT_US: i64 = 60000000 115const NX_SD2_TELEMETRY_PATH: *u8 = "/volume1/homes/elderwesto/nishihost/sites_telemetry.log" as *u8 116const NX_SD2_CIRCLES_DIR: *u8 = "/volume1/homes/elderwesto/nishihost/circles" as *u8 117const NX_SD2_MAX_REQ_PER_CONN: i64 = 64 118// KEEP-ALIVE IDLE BUDGET -- deliberately SEPARATE from the 10s handshake/first-request timeout. 119// THE BUG THIS FIXES (2026-07-31): the child set ONE 10s SO_RCVTIMEO before the handshake and then 120// reused it as the keep-alive idle budget. Every response advertises `Connection: keep-alive` with no 121// timeout hint, so a browser parks the socket for minutes -- but the server dropped it after 10s of 122// silence and tore it down with a bare close. Read any page for >10s, click a link, and the browser 123// writes the request into a connection the server already abandoned, then eats a timeout before 124// retrying on a fresh one. Opening in a NEW TAB was instant because that took a fresh connection. 125// 65s matches the nginx default idle window and is advertised to the client in hr_emit_b, so the 126// client retires the socket BEFORE the server does -- which is what actually closes the race. 127const NX_SD2_KA_IDLE_S: i64 = 65 128// VIEWABLE-impression journal, deliberately SEPARATE from the served-impression journal. Both are kept: 129// served/viewable is the honest delivery ratio for an advertiser, and collapsing them would destroy it. 130const NX_SD2_ADNET_VIEWLOG: *u8 = "/volume1/homes/elderwesto/nishihost/knowledge/status/adnet_viewable.log" as *u8 131// One TLS record (max 16384 payload + header/tag slack) for reads + sends. 132const NX_SD2_RECCAP: i64 = 20480 133// Request plaintext reassembly cap (headers + POST bodies). 2MiB (was 64KB): the PROXIED-route body fill 134// (sd2_fill_body) buffers a full upload chunk here before forwarding, so API clients can send ~1MB chunks 135// instead of 8KB (80MB tree sync: ~10k requests -> ~80). mmap = virtual; only touched pages cost RAM. 136// Mirrors the mgmt daemon's MA_UPLOAD_REQCAP=2MiB so edge and backend agree on the per-request ceiling. 137const NX_SD2_PLAINCAP: i64 = 2097152 138// Out-record scratch for the chunked sender (one wire record). 139const NX_SD2_OUTREC: i64 = 17408 140// Dynamic/file serve buffer: 8MB so a 60s circle webm can be played back. 141const NX_SD2_DYN_CAP: i64 = 8388608 // assembled-response buffer (dynamic pages). Oversize STATICS no longer bound by this: they take the HR_S2_STREAM zero-ceiling path (debt 1785879638 root fix; the interim 32MiB bump is REVERTED -- no magic ceilings) 142const NX_SD2_HDR_RESERVE: i64 = 1024 // baked-page buffer header reserve: must exceed sd2_build_resp's header size (status+ctype+len+SOTA security-header set) 143// SOTA response security headers (OWASP secure-headers set), shared by every sd2-emitted page. Held as a 144// named const so the HSTS max-age is config, not an inline magic (rule 11). Mirrors the hr_emit_b file-serve path. 145const NX_SD2_SEC_HDRS: *u8 = "\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\nContent-Security-Policy: default-src 'self'; img-src 'self' data: blob:; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; font-src 'self' data:; connect-src 'self'; media-src 'self'; frame-ancestors 'self'; base-uri 'none'; object-src 'none'" 146const NX_SD2_STREAM_CHUNK: i64 = 262144 // 256KB read/encrypt window for the streaming reverse-proxy (media) 147// Circle upload hard cap (policy; keep in sync with client MAX_CIRCLE_SECS). 148const NX_SD2_CIRCLE_MAX: i64 = 33554432 149// seq332 edge-DoS guard: a proxied body larger than the reassembly cap CANNOT be buffered whole, so the old 150// path truncated it + forwarded a partial body -> the backend blocked on bytes that never came, each child 151// pinned ~10MB for its 30s upstream timeout, and repeated oversize POSTs saturated MAX_CHILDREN -> OOM crash 152// loop (sig=9 reaps). Reject beyond-capacity bodies fast with 413 + close. Bodies <= PLAINCAP are unchanged; 153// bodies > PLAINCAP were already broken (truncated), so no legitimate upload regresses. 154const RESP2_413: *u8 = "HTTP/1.1 413 Payload Too Large\r\nContent-Length: 0\r\nConnection: close\r\n\r\n" 155// WS pump idle cap (ms): no traffic either direction for this long -> close. 156const NX_SD2_WS_IDLE_MS: i64 = 180000 157const NX_SD2_STATUS_CAP: i64 = 65536 158const NX_SD2_ART_CAP: i64 = 65536 159const RESP2_FAVICON: *u8 = "HTTP/1.1 204 No Content\r\nConnection: keep-alive\r\n\r\n" as *u8 160// Bare /video (no trailing slash) -> /video/ so hr_resolve serves index.html. 161const RESP2_VIDEO_301: *u8 = "HTTP/1.1 301 Moved Permanently\r\nLocation: /video/index.html\r\nContent-Length: 0\r\nConnection: keep-alive\r\n\r\n" as *u8 162// top-level /advertising -> 301 to the OPAQUE-gated census page (operator-only; never a public byte -- the 163// target lives behind the wiki OPAQUE wall). Added 2026-06-20. 164const RESP2_ADV_301: *u8 = "HTTP/1.1 301 Moved Permanently\r\nLocation: /wiki/advertising.html\r\nContent-Length: 0\r\nConnection: keep-alive\r\n\r\n" as *u8 165// FAIL-CLOSED bounce for gated branches (/wiki, /hub) when their OPAQUE gateway is unreachable: redirect to the 166// login page rather than EVER falling through to the unguarded :51850 wiki engine or static wiki files. Operator 167// law: a gated area must never leak content without the OPAQUE gate, even when the backend is momentarily down. 168const RESP2_GATE_LOGIN: *u8 = "HTTP/1.1 302 Found\r\nLocation: /login\r\nContent-Length: 0\r\nConnection: keep-alive\r\n\r\n" as *u8 169// bare /status and /status/ -> the live status dashboard (the supervisor emits status.html every poll). 170const RESP2_STATUS_301: *u8 = "HTTP/1.1 301 Moved Permanently\r\nLocation: /status.html\r\nContent-Length: 0\r\nConnection: keep-alive\r\n\r\n" as *u8 171 172const BODY2_ANDELIN: *u8 = "<!DOCTYPE html>\n<html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>Andelin West Law - Coming Soon</title><style>body{font-family:Georgia,serif;max-width:680px;margin:8vh auto;padding:0 24px;color:#1a1a2e;line-height:1.6}h1{font-size:2rem}.tag{color:#555}.note{margin-top:2rem;padding:16px 20px;background:#f4f4f8;border-left:4px solid #2a4d8f;font-size:.95rem}.foot{margin-top:3rem;font-size:.8rem;color:#888}</style></head><body><h1>Andelin West Law</h1><p class=\"tag\">A modern legal practice. Site launching soon.</p><div class=\"note\"><strong>Placeholder page.</strong> Served by the sovereign Nishi substrate. The full site is pending attorney review of state-bar advertising rules, ADA accessibility conformance, and the privacy notice before any client-facing or intake content goes live.</div><p class=\"foot\">Served bits-up by the Nishi stack &mdash; TLS 1.3, no third-party web server.</p></body></html>\n" as *u8 173 174const BODY2_WIKI: *u8 = "<!DOCTYPE html>\n<html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>Nishi Ecosystem Wiki</title><style>body{font-family:-apple-system,Segoe UI,Roboto,sans-serif;max-width:760px;margin:6vh auto;padding:0 24px;color:#161622;line-height:1.65}h1{font-size:2.1rem}h2{font-size:1.1rem;margin-top:2rem;color:#2a4d8f}ul{padding-left:1.2rem}li{margin:.35rem 0}.note{padding:14px 18px;background:#eef2fb;border-left:4px solid #2a4d8f;border-radius:4px;font-size:.95rem}code{background:#f0f0f4;padding:1px 5px;border-radius:3px;font-size:.9em}.foot{margin-top:3rem;font-size:.8rem;color:#888}</style></head><body><h1>Nishi Ecosystem Wiki</h1><p class=\"note\"><strong>Launch placeholder &mdash; the live wiki engine is coming online.</strong> What you are reading is itself served bits-up by the substrate below: no nginx, no OpenSSL, no libc.</p><p style=\"margin:1.2rem 0\"><a href=\"/wiki/status\"><strong>&#9656; Live stack scorecard &rarr;</strong></a> &nbsp; <a href=\"/wiki/components\"><strong>&#9656; Component articles (Gitea&times;Wikipedia) &rarr;</strong></a></p><h2>Shipped substrate</h2><ul><li>Self-hosting NishiLang compiler (RV64 + x86_64), bits-up from C bootstrap</li><li>TLS 1.3 server &mdash; serving this page now</li><li>SHA-256/512, ChaCha20-Poly1305, AES-GCM, HKDF, Argon2id &mdash; all KAT-verified</li><li>Sovereign secrets vault (HashiCorp-class, ChaCha20-Poly1305 at rest)</li><li>Multi-vhost HTTPS daemon + N-party video signaling (wss) + circles store</li></ul><h2>In progress</h2><ul><li>Full wiki engine (search index, doc store, markdown render)</li><li>Modern auth (OPAQUE PAKE + BIP39 recovery, no cookies)</li><li>Multi-agent concurrent editing (CRDT, sovereign)</li></ul><p class=\"foot\">nishifamily.com/wiki &mdash; bits-up sovereign hosting on the west NAS.</p></body></html>\n" as *u8 175 176// Return-aware bootstrap for a TOP-LEVEL /wiki navigation with NO session header (no-cookie model: a nav 177// never carries X-Nishi-Session). If a token is in sessionStorage -> fetch the same path WITH the header 178// (-> proxied to the wiki gateway -> renders content in place); else -> /login?return=<path> so the fixed 179// login() lands the member back EXACTLY where they were. Replaces the wiki gateway's stale board()->hub login. 180const BODY2_WIKI_BOOTSTRAP: *u8 = "<!doctype html><html><head><meta charset=utf-8><meta name=viewport content='width=device-width,initial-scale=1'><title>Nishi</title></head><body><script>var t=sessionStorage.getItem('nsess');function go(){location='/login?return='+encodeURIComponent(location.pathname+location.search)}function R(h){document.open();document.write(h);document.close()}function F(p,nx){fetch(p,{headers:{'X-Nishi-Session':t}}).then(function(r){return r.ok?r.text():null}).then(function(h){if(h){R(h)}else{nx()}}).catch(go)}if(t){var p=location.pathname,s=location.search;F(p+s,function(){F(p+'.html'+s,go)})}else{go()}</script></body></html>" as *u8 181 182const BODY2_FAMILY: *u8 = "<!DOCTYPE html>\n<html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>Nishi Family</title><style>body{font-family:-apple-system,Segoe UI,Roboto,sans-serif;max-width:680px;margin:8vh auto;padding:0 24px;color:#161622;line-height:1.65;text-align:center}h1{font-size:2.3rem}.tag{color:#555;font-size:1.05rem}a{color:#2a4d8f}.links a{display:inline-block;margin:8px 14px;font-size:1.1rem}.foot{margin-top:3rem;font-size:.8rem;color:#888}</style></head><body><h1>Nishi Family</h1><p class=\"tag\">The family hub &mdash; home of the Nishi sovereign ecosystem.</p><p class=\"links\"><a href=\"/video\">&#127909; Family Video &rarr;</a> <a href=\"/wiki\">Wiki &rarr;</a></p><p class=\"foot\">Served bits-up by the Nishi stack &mdash; TLS 1.3, no third-party web server.</p></body></html>\n" as *u8 183 184func sd2_strlen(s: *u8) -> i64 { 185 var n: i64 = 0 186 while s[n] != 0 { n = n + 1 } 187 return n 188} 189 190// Load a concat-DER fullchain; 0 if absent or implausibly short (mirrors the gated sd_load_chain). 191func sd2_load_chain(path: *u8, len_box: *i64) -> *u8 { 192 len_box[0] = 0 193 let p: *u8 = sys_read_file(path, len_box) 194 if (p as i64) == 0 { return 0 as *u8 } 195 if len_box[0] < 100 { return 0 as *u8 } 196 return p 197} 198 199// Load a 32-byte P-256 ECDSA private scalar; 0 if absent / wrong size (mirrors sd_load_key). 200func sd2_load_key(path: *u8) -> *u8 { 201 let lb: *i64 = (sys_mmap(8)) as *i64 202 lb[0] = 0 203 let p: *u8 = sys_read_file(path, lb) 204 if (p as i64) == 0 { return 0 as *u8 } 205 if lb[0] != 32 { return 0 as *u8 } 206 return p 207} 208 209// ---- DATA-DRIVEN SNI cert table (R1b 2026-07-15) ------------------------------------------------- 210// Every HTTPS domain = one manifest row (suffix + fullchain-der + ecdsa-key). Add a domain = drop its 211// le_<domain>_* + a manifest line; NEVER an edge recompile. Row 0 = the DEFAULT cert. 212const NX_SD2_CERT_MANIFEST: *u8 = "/volume1/homes/elderwesto/nishihost/certs/sni_certs.manifest" as *u8 213const NX_SD2_CERT_MAX: i64 = 32 214 215// Copy one whitespace-delimited field from buf[pos..end) into out (NUL-terminated). Skips leading 216// spaces/tabs. Returns the position past the field, or -1 if the line has no field (blank/'#'/EOL). 217func sd2_field(buf: *u8, pos: i64, end: i64, out: *u8, out_cap: i64) -> i64 { 218 var p: i64 = pos 219 var skip: i64 = 1 220 while skip == 1 { 221 if p >= end { skip = 0 } 222 else { 223 let c: i64 = buf[p] as i64 224 if c == 32 { p = p + 1 } 225 else { if c == 9 { p = p + 1 } else { skip = 0 } } 226 } 227 } 228 if p >= end { return 0 - 1 } 229 let c0: i64 = buf[p] as i64 230 if c0 == 10 { return 0 - 1 } 231 if c0 == 13 { return 0 - 1 } 232 if c0 == 35 { return 0 - 1 } 233 var o: i64 = 0 234 var cp: i64 = 1 235 while cp == 1 { 236 if p >= end { cp = 0 } 237 else { 238 let c: i64 = buf[p] as i64 239 if c == 32 { cp = 0 } 240 else { if c == 9 { cp = 0 } 241 else { if c == 10 { cp = 0 } 242 else { if c == 13 { cp = 0 } 243 else { 244 if o < out_cap - 1 { out[o] = buf[p] as u8; o = o + 1 } 245 p = p + 1 246 } } } } 247 } 248 } 249 out[o] = 0 as u8 250 return p 251} 252 253// Advance past the current line (to the byte after the next '\n', or to end). 254func sd2_next_line(buf: *u8, pos: i64, end: i64) -> i64 { 255 var p: i64 = pos 256 var go: i64 = 1 257 while go == 1 { 258 if p >= end { go = 0 } 259 else { if (buf[p] as i64) == 10 { p = p + 1; go = 0 } else { p = p + 1 } } 260 } 261 return p 262} 263 264// Parse the manifest into parallel arrays; load each row's cert+key. Rows whose cert/key fail to load 265// are skipped (fail-safe). Returns rows loaded (0 => caller uses the legacy fallback). 266func sd2_load_cert_table(man: *u8, man_n: i64, 267 suf_ptrs: *i64, suf_lens: *i64, 268 cert_ptrs: *i64, cert_lens: *i64, key_ptrs: *i64, 269 max: i64) -> i64 { 270 var count: i64 = 0 271 var pos: i64 = 0 272 while pos < man_n { 273 if count >= max { pos = man_n } 274 else { 275 let sufb: *u8 = sys_mmap(256) 276 let p1: i64 = sd2_field(man, pos, man_n, sufb, 256) 277 if p1 < 0 { pos = sd2_next_line(man, pos, man_n) } 278 else { 279 let certp: *u8 = sys_mmap(512) 280 let p2: i64 = sd2_field(man, p1, man_n, certp, 512) 281 if p2 < 0 { pos = sd2_next_line(man, pos, man_n) } 282 else { 283 let keyp: *u8 = sys_mmap(512) 284 let p3: i64 = sd2_field(man, p2, man_n, keyp, 512) 285 if p3 < 0 { pos = sd2_next_line(man, pos, man_n) } 286 else { 287 let clb: *i64 = (sys_mmap(8)) as *i64 288 clb[0] = 0 289 let cbuf: *u8 = sd2_load_chain(certp, clb) 290 let kbuf: *u8 = sd2_load_key(keyp) 291 if (cbuf as i64) == 0 { pos = sd2_next_line(man, pos, man_n) } 292 else { if (kbuf as i64) == 0 { pos = sd2_next_line(man, pos, man_n) } 293 else { 294 var sl: i64 = 0 295 while sufb[sl] != (0 as u8) { sl = sl + 1 } 296 suf_ptrs[count] = sufb as i64 297 suf_lens[count] = sl 298 cert_ptrs[count] = cbuf as i64 299 cert_lens[count] = clb[0] 300 key_ptrs[count] = kbuf as i64 301 count = count + 1 302 pos = sd2_next_line(man, pos, man_n) 303 } } 304 } 305 } 306 } 307 } 308 } 309 return count 310} 311 312// (mtime,size) signature for HOT-RELOAD change detection. out2[0]=st_mtime out2[1]=st_size 313// (x86_64 struct stat: mtime byte 88 = i64[11], size byte 48 = i64[6] -- same convention as 314// nx_torrent_up/nx_torrent_daemon). Returns 0 ok / -1 stat-fail. Comparing BOTH catches a 315// same-second rewrite (mtime granularity) via the size delta. 316func sd2_statsig(path: *u8, statb: *u8, out2: *i64) -> i64 { 317 if sys_fstatat(path, statb) != 0 { out2[0] = 0 - 1; out2[1] = 0 - 1; return 0 - 1 } 318 let sb: *i64 = statb as *i64 319 out2[0] = sb[11] 320 out2[1] = sb[6] 321 return 0 322} 323 324func sd2_contains(hay: *u8, hlen: i64, needle: *u8, nlen: i64) -> i64 { 325 if nlen <= 0 { return 0 } 326 if hlen < nlen { return 0 } 327 var i: i64 = 0 328 let last: i64 = hlen - nlen 329 while i <= last { 330 var j: i64 = 0 331 var ok: i64 = 1 332 while j < nlen { 333 if hay[i + j] != needle[j] { ok = 0; j = nlen } else { j = j + 1 } 334 } 335 if ok == 1 { return 1 } 336 i = i + 1 337 } 338 return 0 339} 340 341func sd2_lower(c: u8) -> u8 { 342 if c >= (65 as u8) { if c <= (90 as u8) { return (c + (32 as u8)) } } 343 return c 344} 345 346// case-insensitive contains (Upgrade/upgrade, WebSocket/websocket...) 347func sd2_contains_ci(hay: *u8, hlen: i64, needle: *u8, nlen: i64) -> i64 { 348 if nlen <= 0 { return 0 } 349 if hlen < nlen { return 0 } 350 var i: i64 = 0 351 let last: i64 = hlen - nlen 352 while i <= last { 353 var j: i64 = 0 354 var ok: i64 = 1 355 while j < nlen { 356 if sd2_lower(hay[i + j]) != sd2_lower(needle[j]) { ok = 0; j = nlen } else { j = j + 1 } 357 } 358 if ok == 1 { return 1 } 359 i = i + 1 360 } 361 return 0 362} 363 364func sd2_body_start(hay: *u8, hlen: i64) -> i64 { 365 if hlen < 4 { return hlen } 366 var i: i64 = 0 367 let last: i64 = hlen - 4 368 while i <= last { 369 if hay[i] == (0x0D as u8) { if hay[i + 1] == (0x0A as u8) { if hay[i + 2] == (0x0D as u8) { if hay[i + 3] == (0x0A as u8) { 370 return i + 4 371 } } } } 372 i = i + 1 373 } 374 return hlen 375} 376 377func sd2_u64_to_dec(n: i64, buf: *u8) -> i64 { 378 if n == 0 { buf[0] = 48; return 1 } 379 var d: i64 = 0 380 var x: i64 = n 381 while x > 0 { d = d + 1; x = x / 10 } 382 var i: i64 = d - 1 383 x = n 384 while i >= 0 { 385 buf[i] = (48 + (x % 10)) as u8 386 x = x / 10 387 i = i - 1 388 } 389 return d 390} 391 392func sd2_append(dst: *u8, off: i64, src: *u8, n: i64) -> i64 { 393 var i: i64 = 0 394 while i < n { dst[off + i] = src[i]; i = i + 1 } 395 return off + n 396} 397 398func sd2_append_str(dst: *u8, off: i64, s: *u8) -> i64 { 399 return sd2_append(dst, off, s, sd2_strlen(s)) 400} 401 402// Full HTTP/1.1 keep-alive response into out (baked pages, built at startup). 403func sd2_build_resp(out: *u8, ctype: *u8, body: *u8, body_len: i64) -> i64 { 404 var w: i64 = 0 405 w = sd2_append_str(out, w, "HTTP/1.1 200 OK\r\nContent-Type: " as *u8) 406 w = sd2_append_str(out, w, ctype) 407 w = sd2_append_str(out, w, "\r\nContent-Length: " as *u8) 408 let dbuf: *u8 = sys_mmap(24) 409 let dn: i64 = sd2_u64_to_dec(body_len, dbuf) 410 w = sd2_append(out, w, dbuf, dn) 411 w = sd2_append_str(out, w, "\r\nConnection: keep-alive" as *u8) 412 w = sd2_append_str(out, w, NX_SD2_SEC_HDRS) 413 w = sd2_append_str(out, w, "\r\nX-Served-By: nishi-substrate-v2\r\n\r\n" as *u8) 414 w = sd2_append(out, w, body, body_len) 415 return w 416} 417 418// Parse "Content-Length:" value from the request headers; -1 if absent. 419func sd2_content_length(req: *u8, reqn: i64) -> i64 { 420 let key: *u8 = "content-length:" as *u8 421 var i: i64 = 0 422 while i + 15 <= reqn { 423 var j: i64 = 0 424 var ok: i64 = 1 425 while j < 15 { 426 if sd2_lower(req[i + j]) != key[j] { ok = 0; j = 15 } else { j = j + 1 } 427 } 428 if ok == 1 { 429 var k: i64 = i + 15 430 while k < reqn { if req[k] == (32 as u8) { k = k + 1 } else { break } } 431 var v: i64 = 0 432 var got: i64 = 0 433 // flag-style digit loop (NO continue-in-nested-if -- that 434 // construct miscompiles under the 2026-06-09 compiler, child hangs) 435 var run: i64 = 1 436 while run == 1 { 437 if k >= reqn { run = 0 } 438 else { 439 let c: i64 = req[k] as i64 440 var dig: i64 = 0 441 if c >= 48 { if c <= 57 { dig = 1 } } 442 if dig == 1 { v = v * 10 + (c - 48); got = 1; k = k + 1 } 443 else { run = 0 } 444 } 445 } 446 if got == 1 { return v } 447 return 0 - 1 448 } 449 i = i + 1 450 } 451 return 0 - 1 452} 453 454// Extract a query parameter value (sanitized to [a-z0-9-], lowercased, 455// max 32 bytes) from the request line. key like "room=". Returns length. 456// Written in strict flag style throughout -- break/continue inside nested 457// ifs miscompile under the 2026-06-09 compiler (child hangs; see the 458// wsupgrade-miscompile repro note). 459func sd2_query_param(req: *u8, reqn: i64, key: *u8, keyn: i64, out: *u8) -> i64 { 460 // only scan the first line (request line) 461 var lim: i64 = 0 462 var scanning: i64 = 1 463 while scanning == 1 { 464 if lim >= reqn { scanning = 0 } 465 else { 466 if req[lim] == (13 as u8) { scanning = 0 } 467 else { lim = lim + 1 } 468 } 469 } 470 // find "key" in the request line 471 var found: i64 = 0 - 1 472 var i: i64 = 0 473 while i + keyn <= lim { 474 if found < 0 { 475 var j: i64 = 0 476 var ok: i64 = 1 477 while j < keyn { 478 if req[i + j] != key[j] { ok = 0; j = keyn } else { j = j + 1 } 479 } 480 if ok == 1 { found = i + keyn } 481 } 482 i = i + 1 483 } 484 if found < 0 { return 0 } 485 // copy sanitized value 486 var k: i64 = found 487 var w: i64 = 0 488 var run: i64 = 1 489 while run == 1 { 490 if k >= lim { run = 0 } 491 else { 492 if w >= 32 { run = 0 } 493 else { 494 let c: u8 = sd2_lower(req[k]) 495 var keepc: i64 = 0 496 if c >= (97 as u8) { if c <= (122 as u8) { keepc = 1 } } 497 if c >= (48 as u8) { if c <= (57 as u8) { keepc = 1 } } 498 if c == (45 as u8) { keepc = 1 } 499 if keepc == 0 { run = 0 } 500 else { out[w] = c; w = w + 1; k = k + 1 } 501 } 502 } 503 } 504 return w 505} 506 507// Receive one HTTP request: read TLS records and reassemble plaintext until the headers (CRLFCRLF) AND, for a 508// POST/PUT carrying a Content-Length, the FULL body. v1 returned at CRLFCRLF and NEVER read the body -- so a 509// client that put the POST body in a separate TLS record (HttpWebRequest, and some mobile browsers) had its 510// body DROPPED: the OPAQUE login daemon then saw an empty handle+pw -> 400/401, making login impossible for 511// EVERY gated service (gallery/wiki/hub/torrent). GETs (no body) still return at the headers. SMALL bodies 512// (login/register/forms) are completed here; LARGE bodies (uploads) are left for their streaming handler so 513// we never force-buffer a multi-MB upload. Returns plaintext length, <=0 on error/EOF. 514func sd2_recv_request(s: *Tls13ServerSession, cfd: i64, rec_buf: *u8, plain: *u8, plain_cap: i64) -> i64 { 515 var total: i64 = 0 516 var recs: i64 = 0 517 var need: i64 = 0 // 0 until headers seen; then = body_start + Content-Length (the full-request byte target) 518 while recs < 8 { 519 let rn: i64 = nx_tls13_read_record_from_fd(cfd, rec_buf, NX_SD2_RECCAP) 520 if rn <= 0 { if total > 0 { return total } return 0 - 1 } 521 let pn: i64 = nx_tls13_server_session_app_recv(s, rec_buf, rn, (plain as i64 + total) as *u8, plain_cap - total) 522 if pn <= 0 { if total > 0 { return total } return 0 - 1 } 523 total = total + pn 524 if need == 0 { 525 // headers complete yet? (CRLFCRLF present) 526 if sd2_contains(plain, total, "\r\n\r\n" as *u8, 4) == 1 { 527 let bs: i64 = sd2_body_start(plain, total) 528 let cl: i64 = sd2_content_length(plain, total) 529 if cl <= 0 { return total } // GET / no body -> done at the headers 530 if cl > NX_MAGIC_8192 { return total } // large body (upload) -> its streaming handler reads the rest 531 need = bs + cl // small body -> keep reading until the whole body arrives 532 if total >= need { return total } // ... already fully present in this record 533 } 534 } else { 535 if total >= need { return total } // small body now complete across records 536 } 537 recs = recs + 1 538 } 539 return total 540} 541 542// Complete a PROXIED request's body in `plain` before forwarding: sd2_recv_request stops at the headers for 543// bodies >8KB (streaming handlers read their own body), but the buffered reverse-proxy is NOT such a handler -- 544// it forwarded whatever was buffered, TRUNCATING any body spanning >1 TLS record (the hard 8KB upload-chunk cap; 545// backends then waited on bytes that never came). This reads TLS records until body_start+Content-Length, bounded 546// by plain_cap and a record budget. FAIL-SAFE BY CONSTRUCTION: on any error/timeout/oversize it returns what is 547// buffered -- exactly the old forward-partial behavior, so no failure mode is NEW; the backend's own 548// Content-Length handling still applies. Pump pattern mirrors the proven sd2_circle_upload reader. 549func sd2_fill_body(s: *Tls13ServerSession, cfd: i64, rec_buf: *u8, plain: *u8, have: i64, plain_cap: i64) -> i64 { 550 if sd2_contains(plain, have, "\r\n\r\n" as *u8, 4) == 0 { return have } // headers incomplete -> old behavior 551 let cl: i64 = sd2_content_length(plain, have) 552 if cl <= 0 { return have } // GET / no declared body -> nothing to fill 553 let bs: i64 = sd2_body_start(plain, have) // CRLFCRLF proven present, so bs is the true body offset 554 var need: i64 = bs + cl 555 if need > plain_cap { need = plain_cap } // oversize: forward the first plain_cap bytes (backend refuses) 556 var total: i64 = have 557 var recs: i64 = 0 558 while total < need { 559 if recs >= 512 { return total } // budget backstop (2MiB / ~4KB-min records) 560 let rn: i64 = nx_tls13_read_record_from_fd(cfd, rec_buf, NX_SD2_RECCAP) 561 if rn <= 0 { return total } 562 let pn: i64 = nx_tls13_server_session_app_recv(s, rec_buf, rn, (plain as i64 + total) as *u8, plain_cap - total) 563 if pn <= 0 { return total } 564 total = total + pn 565 recs = recs + 1 566 } 567 return total 568} 569 570// ---- D4: TLS-terminating WebSocket pump to loopback nx_signaling_v2 ---- 571func sd2_ws_pump(s: *Tls13ServerSession, cfd: i64, first_req: *u8, first_n: i64, 572 rec_buf: *u8, out_rec: *u8, pump: *u8) -> i64 { 573 // connect 127.0.0.1:8445 574 let ufd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0) 575 if ufd < 0 { return 0 - 1 } 576 let addr: *u8 = sys_mmap(16) 577 addr[0] = 2 as u8; addr[1] = 0 as u8 578 addr[2] = ((NX_MAGIC_8445 >> 8) & 0xff) as u8 579 addr[3] = (NX_MAGIC_8445 & 0xff) as u8 580 addr[4] = 127 as u8; addr[5] = 0 as u8; addr[6] = 0 as u8; addr[7] = 1 as u8 581 var zi: i64 = 8 582 while zi < 16 { addr[zi] = 0 as u8; zi = zi + 1 } 583 if nx_connect_bounded(ufd, addr, 16, NX_CONN_DEFAULT_MS) < 0 { sys_close(ufd); return 0 - 1 } 584 585 // TCP_NODELAY (IPPROTO_TCP=6, TCP_NODELAY=1) on the UPSTREAM pump socket: this hop carries 586 // every live video/audio frame to the relay. Without it, Nagle here x delayed-ACK on the 587 // relay side adds up to ~40ms per frame burst -- MEASURED live by nx_video_qoe_live 588 // 2026-07-03 (an exact ~40ms cycle floor above 25fps that client-side nodelay did NOT fix). 589 // Mirrors the nodelay this daemon already sets on its public accept sockets. 590 let pnd: *u8 = sys_mmap(4) 591 pnd[0] = 1 as u8 592 pnd[1] = 0 as u8 593 pnd[2] = 0 as u8 594 pnd[3] = 0 as u8 595 sys_setsockopt(ufd, 6, 1, pnd, 4) 596 597 // forward the decrypted upgrade request; the signaling daemon answers 101 598 if nx_tls13_sendfd_write_all(ufd, first_req, first_n) < 0 { sys_close(ufd); return 0 - 1 } 599 600 // long-lived call: lift the 10s accept-time read timeout (poll bounds idle) 601 sys_set_socket_timeout(cfd, 600) 602 let pfds: *u8 = sys_mmap(2 * NX_POLLFD_BYTES) 603 var alive: i64 = 1 604 while alive == 1 { 605 nx_pollfd_set(pfds, 0, cfd, NX_POLLIN) 606 nx_pollfd_set(pfds, 1, ufd, NX_POLLIN) 607 let nr: i64 = nx_poll(pfds, 2, NX_SD2_WS_IDLE_MS) 608 if nr <= 0 { alive = 0 } // idle cap or error -> close 609 if alive == 1 { 610 if (nx_pollfd_revents(pfds, 0) & NX_POLLIN) != 0 { 611 let rn: i64 = nx_tls13_read_record_from_fd(cfd, rec_buf, NX_SD2_RECCAP) 612 if rn <= 0 { alive = 0 } 613 else { 614 let pn: i64 = nx_tls13_server_session_app_recv(s, rec_buf, rn, pump, NX_SD2_RECCAP) 615 if pn <= 0 { alive = 0 } 616 else { 617 if nx_tls13_sendfd_write_all(ufd, pump, pn) < 0 { alive = 0 } 618 } 619 } 620 } 621 } 622 if alive == 1 { 623 if (nx_pollfd_revents(pfds, 1) & NX_POLLIN) != 0 { 624 let un: i64 = sys_read(ufd, pump, NX_MAGIC_16000) 625 if un <= 0 { alive = 0 } 626 else { 627 if nx_tls13_app_send_fd(s, pump, un, cfd, out_rec, NX_SD2_OUTREC) < 0 { alive = 0 } 628 } 629 } 630 } 631 } 632 sys_close(ufd) 633 return 0 634} 635 636// ---- D5: circles ---- 637 638// Build "<dir>/<sub>/<room>_<from>_<usec>.<ext>" into out; returns len. 639// ext_nv1=1 -> ".nv1" (NishiLossless v1 circles, see nx_nv1.nx); else ".webm" 640// (legacy MediaRecorder circles -- still served for back-compat playback). 641func sd2_circle_path(out: *u8, priv: i64, room: *u8, room_n: i64, 642 from: *u8, from_n: i64, usec: i64, ext_nv1: i64) -> i64 { 643 var w: i64 = 0 644 w = sd2_append_str(out, w, NX_SD2_CIRCLES_DIR) 645 if priv == 1 { w = sd2_append_str(out, w, "/private/" as *u8) } 646 else { w = sd2_append_str(out, w, "/public/" as *u8) } 647 w = sd2_append(out, w, room, room_n) 648 out[w] = 95; w = w + 1 // '_' 649 w = sd2_append(out, w, from, from_n) 650 out[w] = 95; w = w + 1 651 let dbuf: *u8 = sys_mmap(24) 652 let dn: i64 = sd2_u64_to_dec(usec, dbuf) 653 w = sd2_append(out, w, dbuf, dn) 654 if ext_nv1 == 1 { w = sd2_append_str(out, w, ".nv1" as *u8) } 655 else { w = sd2_append_str(out, w, ".webm" as *u8) } 656 out[w] = 0 657 return w 658} 659 660// bounded append of pn received bytes into the body buffer (clamped at the 661// declared content-length); hoisted to a helper to keep the receive loop's 662// nesting shallow (the nested-if miscompile landmine). Returns new got. 663func sd2_body_copy(body: *u8, got: i64, cl: i64, src: *u8, pn: i64) -> i64 { 664 var wn: i64 = pn 665 if got + wn > cl { wn = cl - got } 666 var pi: i64 = 0 667 while pi < wn { body[got + pi] = src[pi]; pi = pi + 1 } 668 return got + pn 669} 670 671// POST /video/circle?room=R&from=F&priv=0|1 -- stream the webm body to the 672// circles store. Response written into dyn (small JSON). Returns resp len. 673func sd2_circle_upload(s: *Tls13ServerSession, cfd: i64, plain: *u8, plain_n: i64, 674 rec_buf: *u8, pump: *u8, dyn: *u8) -> i64 { 675 let cl: i64 = sd2_content_length(plain, plain_n) 676 var bad: i64 = 0 677 if cl <= 0 { bad = 1 } 678 if cl > NX_SD2_CIRCLE_MAX { bad = 1 } 679 let room: *u8 = sys_mmap(40) 680 let from: *u8 = sys_mmap(40) 681 let pv: *u8 = sys_mmap(40) 682 let room_n: i64 = sd2_query_param(plain, plain_n, "room=" as *u8, 5, room) 683 var from_n: i64 = sd2_query_param(plain, plain_n, "from=" as *u8, 5, from) 684 let pv_n: i64 = sd2_query_param(plain, plain_n, "priv=" as *u8, 5, pv) 685 if room_n == 0 { bad = 1 } 686 if from_n == 0 { from[0] = 120; from_n = 1 } // 'x' 687 var priv: i64 = 0 688 if pv_n == 1 { if pv[0] == (49 as u8) { priv = 1 } } 689 // ext=nv1 -> NishiLossless container suffix (allowlist, not pass-through: 690 // the suffix is the ONLY client-controlled byte sequence in the path) 691 let ex: *u8 = sys_mmap(40) 692 let ex_n: i64 = sd2_query_param(plain, plain_n, "ext=" as *u8, 4, ex) 693 var ext_nv1: i64 = 0 694 if ex_n == 3 { 695 var exm: i64 = 1 696 if ex[0] != (110 as u8) { exm = 0 } // 'n' 697 if ex[1] != (118 as u8) { exm = 0 } // 'v' 698 if ex[2] != (49 as u8) { exm = 0 } // '1' 699 ext_nv1 = exm 700 } 701 if bad == 1 { 702 let b: *u8 = "{\"ok\":0,\"err\":\"bad request\"}" as *u8 703 return hr_emit_b(dyn, NX_SD2_DYN_CAP, "HTTP/1.1 400 Bad Request" as *u8, "application/json" as *u8, b, sd2_strlen(b)) 704 } 705 706 // Receive the FULL body into memory first (cl capped at 707 // NX_SD2_CIRCLE_MAX; anonymous mmap is lazy so only received pages 708 // cost RAM), VALIDATE, and only then touch the circles store: a 709 // truncated or corrupt upload never lands as a stored circle (the 710 // old stream-to-file path left truncated files behind on failure). 711 let body: *u8 = sys_mmap(cl + 64) 712 let bs: i64 = sd2_body_start(plain, plain_n) 713 var got: i64 = plain_n - bs 714 if got > 0 { sd2_body_copy(body, 0, cl, (plain as i64 + bs) as *u8, got) } 715 var fail: i64 = 0 716 while got < cl { 717 let rn: i64 = nx_tls13_read_record_from_fd(cfd, rec_buf, NX_SD2_RECCAP) 718 if rn <= 0 { fail = 1; got = cl } 719 else { 720 let pn: i64 = nx_tls13_server_session_app_recv(s, rec_buf, rn, pump, NX_SD2_RECCAP) 721 if pn <= 0 { fail = 1; got = cl } 722 else { 723 got = sd2_body_copy(body, got, cl, pump, pn) 724 } 725 } 726 } 727 if fail == 1 { 728 sys_write(2, "circle upload TRUNCATED, nothing stored\n" as *u8, 40) 729 let b3: *u8 = "{\"ok\":0,\"err\":\"upload truncated\"}" as *u8 730 return hr_emit_b(dyn, NX_SD2_DYN_CAP, "HTTP/1.1 400 Bad Request" as *u8, "application/json" as *u8, b3, sd2_strlen(b3)) 731 } 732 733 // Server-side NV1 validation (the named rung from the NV1 spec): 734 // ext=nv1 uploads must be a well-formed NLC1 container (raw 'A' or 735 // LPC 'L' audio) or they are REJECTED at the door. Legacy .webm 736 // bodies stay opaque (back-compat playback only). 737 if ext_nv1 == 1 { 738 let vinfo: *i64 = sys_mmap(64) as *i64 739 let vrc: i64 = nv1_validate(body, cl, vinfo) 740 if vrc != 0 { 741 sys_write(2, "circle nv1-invalid rc=-" as *u8, 23) 742 let vd: *u8 = sys_mmap(8) 743 vd[0] = (48 - vrc) as u8 744 sys_write(2, vd, 1) 745 sys_write(2, " rejected, nothing stored\n" as *u8, 26) 746 let b5: *u8 = "{\"ok\":0,\"err\":\"nv1 invalid\"}" as *u8 747 return hr_emit_b(dyn, NX_SD2_DYN_CAP, "HTTP/1.1 400 Bad Request" as *u8, "application/json" as *u8, b5, sd2_strlen(b5)) 748 } 749 } 750 751 // Store dirs are DEPLOY-OWNED (created once by _deploy_content, 0700 on 752 // private). No per-request sys_mkdir: that helper hardcodes rv64 34 753 // (mkdirat) and under the C-bootstrap compiler there is NO rv64->x86 754 // translation -- syscall 34 on x86_64 is pause(), which blocked the 755 // upload child forever (found live 2026-06-10 via CU breadcrumbs). 756 let path: *u8 = sys_mmap(512) 757 let path_n: i64 = sd2_circle_path(path, priv, room, room_n, from, from_n, sys_now_us(), ext_nv1) 758 let ffd: i64 = sys_openat_wr(path, 0x1a4) 759 if ffd < 0 { 760 let b2: *u8 = "{\"ok\":0,\"err\":\"store open failed\"}" as *u8 761 return hr_emit_b(dyn, NX_SD2_DYN_CAP, "HTTP/1.1 500 Internal Server Error" as *u8, "application/json" as *u8, b2, sd2_strlen(b2)) 762 } 763 nx_tls13_sendfd_write_all(ffd, body, cl) 764 sys_close(ffd) 765 // Cardinal 18: one meaningful line per stored circle (path + outcome). 766 sys_write(2, "circle stored " as *u8, 14) 767 sys_write(2, path, path_n) 768 sys_write(2, " ok\n" as *u8, 4) 769 let b4: *u8 = "{\"ok\":1}" as *u8 770 return hr_emit_b(dyn, NX_SD2_DYN_CAP, "HTTP/1.1 200 OK" as *u8, "application/json" as *u8, b4, sd2_strlen(b4)) 771} 772 773// GET /video/circles?room=R[&priv=1] -- JSON list of the room's circles, 774// newest unsorted (client sorts by the embedded usec). priv=1 lists the 775// private archive (review-later view). 776func sd2_circle_list(plain: *u8, plain_n: i64, dyn: *u8) -> i64 { 777 let room: *u8 = sys_mmap(40) 778 let pv: *u8 = sys_mmap(40) 779 let room_n: i64 = sd2_query_param(plain, plain_n, "room=" as *u8, 5, room) 780 let pv_n: i64 = sd2_query_param(plain, plain_n, "priv=" as *u8, 5, pv) 781 var priv: i64 = 0 782 if pv_n == 1 { if pv[0] == (49 as u8) { priv = 1 } } 783 let dirp: *u8 = sys_mmap(256) 784 var dw: i64 = sd2_append_str(dirp, 0, NX_SD2_CIRCLES_DIR) 785 if priv == 1 { dw = sd2_append_str(dirp, dw, "/private" as *u8) } 786 else { dw = sd2_append_str(dirp, dw, "/public" as *u8) } 787 dirp[dw] = 0 788 789 let body: *u8 = sys_mmap(NX_MAGIC_65536) 790 var bw: i64 = 0 791 body[bw] = 91; bw = bw + 1 // '[' 792 var first: i64 = 1 793 let dfd: i64 = sys_openat_rd(dirp) 794 if dfd >= 0 { 795 let dbuf: *u8 = sys_mmap(NX_MAGIC_16384) 796 var more: i64 = 1 797 while more == 1 { 798 let nread: i64 = sys_getdents64(dfd, dbuf, NX_MAGIC_16384) 799 if nread <= 0 { more = 0 } 800 else { 801 var off: i64 = 0 802 while off < nread { 803 // linux_dirent64: u64 ino, i64 off, u16 reclen, u8 type, name... 804 let reclen: i64 = ((dbuf[off + 16] as i64) | ((dbuf[off + 17] as i64) << 8)) 805 let namep: i64 = off + 19 806 var nl: i64 = 0 807 while dbuf[namep + nl] != 0 { nl = nl + 1 } 808 // match "<room>_" prefix + ".webm" suffix; skip . / .. 809 var want: i64 = 0 810 if room_n > 0 { if nl > room_n { 811 var m: i64 = 1 812 var q: i64 = 0 813 while q < room_n { 814 if dbuf[namep + q] != room[q] { m = 0; q = room_n } else { q = q + 1 } 815 } 816 if m == 1 { if dbuf[namep + room_n] == (95 as u8) { want = 1 } } 817 } } 818 if want == 1 { if bw < NX_MAGIC_60000 { 819 if first == 0 { body[bw] = 44; bw = bw + 1 } // ',' 820 body[bw] = 34; bw = bw + 1 // '"' 821 var c2: i64 = 0 822 while c2 < nl { body[bw] = dbuf[namep + c2]; bw = bw + 1; c2 = c2 + 1 } 823 body[bw] = 34; bw = bw + 1 824 first = 0 825 } } 826 if reclen <= 0 { off = nread } else { off = off + reclen } 827 } 828 } 829 } 830 sys_close(dfd) 831 } 832 body[bw] = 93; bw = bw + 1 // ']' 833 return hr_emit_b(dyn, NX_SD2_DYN_CAP, "HTTP/1.1 200 OK" as *u8, "application/json" as *u8, body, bw) 834} 835 836// GET /video/circle/<name> -- play one circle back. Name is taken from the 837// path, sanitized (no '/', no '..'); public first, then private (the 838// review-later view; honest residual: room-name capability is the only 839// auth until OPAQUE lands -- flagged in the deploy log, not hidden). 840func sd2_circle_play(plain: *u8, plain_n: i64, dyn: *u8) -> i64 { 841 // path starts after "GET /video/circle/" 842 let pfx: *u8 = "GET /video/circle/" as *u8 843 let pfxn: i64 = 18 844 var st: i64 = 0 - 1 845 var i: i64 = 0 846 while i + pfxn <= plain_n { 847 var j: i64 = 0 848 var ok: i64 = 1 849 while j < pfxn { 850 if plain[i + j] != pfx[j] { ok = 0; j = pfxn } else { j = j + 1 } 851 } 852 if ok == 1 { st = i + pfxn; i = plain_n } else { i = i + 1 } 853 } 854 if st < 0 { return hr_emit_404(dyn, NX_SD2_DYN_CAP) } 855 let name: *u8 = sys_mmap(256) 856 var nl: i64 = 0 857 while st < plain_n { 858 let c: u8 = plain[st] 859 if c == (32 as u8) { break } 860 if c == (63 as u8) { break } 861 if c == (13 as u8) { break } 862 if c == (47 as u8) { return hr_emit_404(dyn, NX_SD2_DYN_CAP) } // '/' 863 if c == (46 as u8) { if st + 1 < plain_n { if plain[st + 1] == (46 as u8) { return hr_emit_404(dyn, NX_SD2_DYN_CAP) } } } 864 if nl < 250 { name[nl] = c; nl = nl + 1 } 865 st = st + 1 866 } 867 if nl == 0 { return hr_emit_404(dyn, NX_SD2_DYN_CAP) } 868 name[nl] = 0 869 870 let path: *u8 = sys_mmap(512) 871 var w: i64 = sd2_append_str(path, 0, NX_SD2_CIRCLES_DIR) 872 w = sd2_append_str(path, w, "/public/" as *u8) 873 w = sd2_append(path, w, name, nl) 874 path[w] = 0 875 let lenbox: *i64 = (sys_mmap(8)) as *i64 876 lenbox[0] = 0 877 var data: *u8 = sys_read_file(path, lenbox) 878 if (data as i64) == 0 { 879 w = sd2_append_str(path, 0, NX_SD2_CIRCLES_DIR) 880 w = sd2_append_str(path, w, "/private/" as *u8) 881 w = sd2_append(path, w, name, nl) 882 path[w] = 0 883 lenbox[0] = 0 884 data = sys_read_file(path, lenbox) 885 } 886 if (data as i64) == 0 { return hr_emit_404(dyn, NX_SD2_DYN_CAP) } 887 let body_n: i64 = lenbox[0] 888 let w2: i64 = hr_emit_b(dyn, NX_SD2_DYN_CAP, "HTTP/1.1 200 OK" as *u8, "video/webm" as *u8, data, body_n) 889 if w2 < 0 { 890 let b: *u8 = "<!doctype html><h1>500 - circle exceeds serve buffer</h1>" as *u8 891 return hr_emit_b(dyn, NX_SD2_DYN_CAP, "HTTP/1.1 500 Internal Server Error" as *u8, "text/html; charset=utf-8" as *u8, b, sd2_strlen(b)) 892 } 893 return w2 894} 895 896// HTTP reverse-proxy to a loopback backend on 127.0.0.1:<port>. Forwards the already TLS-decrypted 897// request `plain` and reads the backend's full HTTP response into `dyn` (backend MUST close after its 898// response -- both the wiki engine :51850 and the OPAQUE login daemon :9091 send Connection: close + 899// close the fd -> read to EOF). A 15s upstream read timeout guarantees the child can never hang on a 900// stuck backend. Returns response length, or <=0 on failure (caller falls through -- ADDITIVE: a proxy 901// miss never breaks the site). license_tier: ORIGINAL (sovereign reverse proxy -- replaces nginx). 902func sd2_lc(c: i64) -> i64 { if c>=65 { if c<=90 { return c+32 } } return c } 903func sd2_is_conn_line(plain: *u8, p: i64, n: i64) -> i64 { 904 let key: *u8 = "connection:" as *u8 905 var i: i64 = 0 906 while i < 11 { if p+i >= n { return 0 } if sd2_lc(plain[p+i] as i64) != (key[i] as i64) { return 0 } i = i + 1 } 907 return 1 908} 909// Rewrite the upstream request: drop any Connection: header line + insert "Connection: close", keep the body 910// verbatim. ROOT-CAUSE FIX (galxauthprobe proved the gateway answers in 0ms; the hang is here): a keep-alive POST 911// made the backend hold the socket open, so the proxy relay below BLOCKED waiting for a close that never came -> 912// the client timed out (~10s) = "Failed to fetch". Forcing close => the backend closes after replying => clean EOF. 913func sd2_force_close(plain: *u8, n: i64, out: *u8) -> i64 { 914 var he: i64 = 0 - 1 915 var i: i64 = 0 916 while i + 3 < n { 917 if (plain[i] as i64)==13 { if (plain[i+1] as i64)==10 { if (plain[i+2] as i64)==13 { if (plain[i+3] as i64)==10 { he = i + 4 } } } } 918 if he >= 0 { i = n } else { i = i + 1 } 919 } 920 if he < 0 { var k: i64 = 0; while k < n { out[k] = plain[k]; k = k + 1 } return n } 921 var o: i64 = 0 922 var p: i64 = 0 923 let hend: i64 = he - 2 924 while p < hend { 925 var le: i64 = p 926 var found: i64 = 0 927 while found == 0 { 928 if le + 1 >= hend { le = hend; found = 1 } 929 else { if (plain[le] as i64)==13 { if (plain[le+1] as i64)==10 { found = 1 } else { le = le + 1 } } else { le = le + 1 } } 930 } 931 if sd2_is_conn_line(plain, p, n) == 0 { 932 var c: i64 = p 933 var cend: i64 = le + 2 934 if cend > hend { cend = hend } 935 while c < cend { out[o] = plain[c]; o = o + 1; c = c + 1 } 936 } 937 p = le + 2 938 } 939 let cc: *u8 = "Connection: close\r\n\r\n" as *u8 940 var ci: i64 = 0 941 while cc[ci] != (0 as u8) { out[o] = cc[ci]; o = o + 1; ci = ci + 1 } 942 var b: i64 = he 943 while b < n { out[o] = plain[b]; o = o + 1; b = b + 1 } 944 return o 945} 946func sd2_proxy_to(plain: *u8, plain_n: i64, dyn: *u8, port: i64) -> i64 { 947 let ufd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0) 948 if ufd < 0 { return 0 - 1 } 949 let addr: *u8 = sys_mmap(16) 950 addr[0] = 2 as u8; addr[1] = 0 as u8 951 addr[2] = ((port >> 8) & 0xff) as u8 952 addr[3] = (port & 0xff) as u8 953 addr[4] = 127 as u8; addr[5] = 0 as u8; addr[6] = 0 as u8; addr[7] = 1 as u8 954 var zi: i64 = 8 955 while zi < 16 { addr[zi] = 0 as u8; zi = zi + 1 } 956 if nx_connect_bounded(ufd, addr, 16, NX_CONN_DEFAULT_MS) < 0 { sys_close(ufd); return 0 - 1 } 957 sys_set_socket_timeout(ufd, 15) 958 let fcbuf: *u8 = sys_mmap(NX_SD2_PLAINCAP) 959 let fcn: i64 = sd2_force_close(plain, plain_n, fcbuf) 960 var wo: i64 = 0 961 while wo < fcn { let w: i64 = sys_write(ufd, ((fcbuf as i64) + wo) as *u8, fcn - wo); if w <= 0 { sys_close(ufd); return 0 - 1 } wo = wo + w } 962 var off: i64 = 0 963 var reading: i64 = 1 964 while reading == 1 { 965 if off >= NX_SD2_DYN_CAP { reading = 0 } 966 else { 967 let r: i64 = sys_read(ufd, ((dyn as i64) + off) as *u8, NX_SD2_DYN_CAP - off) 968 if r <= 0 { reading = 0 } else { off = off + r } 969 } 970 } 971 sys_close(ufd) 972 return off 973} 974 975// STREAMING reverse-proxy (S-class media: NO 8MB buffer). Connect 127.0.0.1:port, forward the decrypted 976// request, then read the backend response in 256KB windows and TLS-encrypt each straight to the client -- 977// the file is NEVER buffered whole (the way real media servers serve byte-range video: read-chunk -> 978// send-chunk, TCP backpressure paces it; cf. MDN HTTP Range requests / Media Source Extensions). Returns 979// total bytes streamed, or -1 if the backend was unreachable (nothing sent yet -> caller may fall through). 980// license_tier: ORIGINAL (loopback spine from sd2_proxy_to; TLS app-send from sd2_ws_pump). 981func sd2_proxy_stream(s: *Tls13ServerSession, cfd: i64, plain: *u8, plain_n: i64, port: i64, out_rec: *u8) -> i64 { 982 let ufd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0) 983 if ufd < 0 { return 0 - 1 } 984 let addr: *u8 = sys_mmap(16) 985 addr[0] = 2 as u8; addr[1] = 0 as u8 986 addr[2] = ((port >> 8) & 0xff) as u8 987 addr[3] = (port & 0xff) as u8 988 addr[4] = 127 as u8; addr[5] = 0 as u8; addr[6] = 0 as u8; addr[7] = 1 as u8 989 var zi: i64 = 8 990 while zi < 16 { addr[zi] = 0 as u8; zi = zi + 1 } 991 if nx_connect_bounded(ufd, addr, 16, NX_CONN_DEFAULT_MS) < 0 { sys_close(ufd); return 0 - 1 } 992 sys_set_socket_timeout(ufd, 30) 993 let fcbuf: *u8 = sys_mmap(NX_SD2_PLAINCAP) 994 let fcn: i64 = sd2_force_close(plain, plain_n, fcbuf) 995 var wo: i64 = 0 996 while wo < fcn { let w: i64 = sys_write(ufd, ((fcbuf as i64) + wo) as *u8, fcn - wo); if w <= 0 { sys_close(ufd); return 0 - 1 } wo = wo + w } 997 sys_write(1, "PXY-FWD\n" as *u8, 8) 998 sys_set_socket_timeout(cfd, 600) // long-lived media stream: lift the accept-time client read timeout 999 let chunk: *u8 = sys_mmap(NX_SD2_STREAM_CHUNK) 1000 var total: i64 = 0 1001 var go: i64 = 1 1002 var first: i64 = 1 1003 while go == 1 { 1004 let rn: i64 = sys_read(ufd, chunk, NX_SD2_STREAM_CHUNK) 1005 if first == 1 { if rn > 0 { sys_write(1, "PXY-GOT\n" as *u8, 8) } else { sys_write(1, "PXY-EOF0\n" as *u8, 9) } first = 0 } 1006 if rn <= 0 { go = 0 } else { 1007 if nx_tls13_app_send_fd(s, chunk, rn, cfd, out_rec, NX_SD2_OUTREC) < 0 { go = 0 } else { total = total + rn } 1008 } 1009 } 1010 sys_close(ufd) 1011 sys_write(1, "PXY-RET\n" as *u8, 8) 1012 return total 1013} 1014 1015// Wiki engine reverse-proxy (loopback 127.0.0.1:51850). 1016func sd2_wiki_proxy(plain: *u8, plain_n: i64, dyn: *u8) -> i64 { 1017 return sd2_proxy_to(plain, plain_n, dyn, NX_MAGIC_51850) 1018} 1019 1020// seq1306 (sev9, MEASURED 2026-07-30): route matching MUST NOT see the body. Every dispatcher match in 1021// this daemon scanned the WHOLE buffer, so a request whose BODY merely quoted a real route+query was 1022// HIJACKED by that handler (reproducer: uploading this daemon's own source 400'd, deterministic 6/6 -- 1023// the edge could not ship its own fix). It also let a body spoof header checks (X-Nishi-Session, Host, 1024// Accept). Fix: compute the header span ONCE per request and match only within it. Forwarding calls 1025// (sd2_proxy_to / sd2_fill_body) still get the FULL length -- bodies must still be proxied whole. 1026// Returns bytes up to and including the CRLFCRLF terminator, or n when no terminator is present. 1027func sd2_hdr_span(p: *u8, n: i64) -> i64 { 1028 var i: i64 = 0 1029 while i + 3 < n { 1030 if p[i] == (13 as u8) { if p[i+1] == (10 as u8) { if p[i+2] == (13 as u8) { if p[i+3] == (10 as u8) { return i + 4 } } } } 1031 i = i + 1 1032 } 1033 return n 1034} 1035// Is this request one of the OPAQUE login routes (/login, /register, /whoami, /audio)? Matched with a 1036// leading space so it fires only on the request-line path -- âš the leading space does NOT bound it to the 1037// request line (seq1306): callers MUST pass the header span, never the full request length. 1038func sd2_is_login_route(plain: *u8, plain_n: i64) -> i64 { 1039 if sd2_contains(plain, plain_n, " /login" as *u8, 7) == 1 { return 1 } 1040 if sd2_contains(plain, plain_n, " /register" as *u8, 10) == 1 { return 1 } 1041 if sd2_contains(plain, plain_n, " /whoami" as *u8, 8) == 1 { return 1 } 1042 if sd2_contains(plain, plain_n, " /audio" as *u8, 7) == 1 { return 1 } 1043 if sd2_contains(plain, plain_n, " /access" as *u8, 8) == 1 { return 1 } 1044 if sd2_contains(plain, plain_n, " /welcome" as *u8, 9) == 1 { return 1 } 1045 return 0 1046} 1047 1048// PUBLIC CARVE-OUT under the otherwise fully-gated /wiki tree (operator 2026-08-01: product strategy 1049// stays behind the gate, "code can exist without a gate as its fine to share that information and 1050// research as its public"). /wiki/research is the research OCEAN -- the index over every research 1051// river -- and is deliberately readable without a session. Nothing else under /wiki is affected. 1052// BOUNDARY-SAFE BY CONSTRUCTION: only the exact page and its .html / query forms are public, so a 1053// sibling file whose name merely STARTS with "research" (e.g. /wiki/research_private.html) can NOT 1054// ride this carve-out. A prefix match here would be an escape hatch, not a carve-out. 1055func sd2_wiki_public(p: *u8, n: i64) -> i64 { 1056 if sd2_contains(p, n, " /wiki/research " as *u8, 16) == 1 { return 1 } 1057 if sd2_contains(p, n, " /wiki/research.html" as *u8, 20) == 1 { return 1 } 1058 if sd2_contains(p, n, " /wiki/research?" as *u8, 16) == 1 { return 1 } 1059 return 0 1060} 1061// 1 = this request must go through the OPAQUE wiki gate; 0 = not a /wiki path at all, OR an explicitly 1062// public one, which then falls through to normal static routing. Replaces a bare /wiki substring test 1063// at the gate call site so the allowlist lives in ONE named place instead of inline at the branch. 1064func sd2_wiki_gated(p: *u8, n: i64) -> i64 { 1065 if sd2_contains(p, n, " /wiki" as *u8, 6) == 0 { return 0 } 1066 if sd2_wiki_public(p, n) == 1 { return 0 } 1067 return 1 1068} 1069 1070func sd2_atoi(s: *u8) -> i64 { var v: i64=0; var i: i64=0; while s[i]!=(0 as u8){ let c: i64=s[i] as i64; if c<48{return v} if c>57{return v} v=v*10+(c-48); i=i+1 } return v } 1071 1072func main(argc: i64, argv: *i64) -> i64 { 1073 // listen port: argv[1] overrides NX_SD2_PORT (default 8443). Lets a fresh build be 1074 // scratch-tested on a spare port without disturbing the live :8443 daemon. 1075 var listen_port: i64 = NX_SD2_PORT 1076 if argc > 1 { listen_port = sd2_atoi(argv[1] as *u8) } 1077 // ---- Route B: load the per-domain wildcard pairs; PAIRED fail-safe to the generic pair ---- 1078 // NISHI (index 0) = the default for absent/garbled/unknown SNI. If its per-domain pair is 1079 // incomplete, the legacy generic both-SAN pair serves it (exactly today's behavior). 1080 let cert_len_box: *i64 = (sys_mmap(8)) as *i64 1081 var cert_nishi: *u8 = sd2_load_chain(NX_SD2_CERT_NISHI, cert_len_box) 1082 var cert_nishi_len: i64 = cert_len_box[0] 1083 var ecdsa_nishi: *u8 = sd2_load_key(NX_SD2_PRIV_NISHI) 1084 var nishi_src: i64 = 1 // 1 = per-domain files, 0 = generic fallback 1085 if (cert_nishi as i64) == 0 { nishi_src = 0 } 1086 if (ecdsa_nishi as i64) == 0 { nishi_src = 0 } 1087 if nishi_src == 0 { 1088 cert_nishi = sd2_load_chain(NX_SD2_CERT_PATH, cert_len_box) 1089 cert_nishi_len = cert_len_box[0] 1090 ecdsa_nishi = sd2_load_key(NX_SD2_PRIV_PATH) 1091 } 1092 if (cert_nishi as i64) == 0 { return 2 } 1093 if (ecdsa_nishi as i64) == 0 { return 3 } 1094 1095 // ANDELIN (index 1). PAIRED fail-safe: any missing/short file -> serve the NISHI pair for 1096 // andelinwest hosts (a valid handshake still completes; never a mismatched cert/key). 1097 let andelin_len_box: *i64 = (sys_mmap(8)) as *i64 1098 var cert_andelin: *u8 = sd2_load_chain(NX_SD2_CERT_ANDELIN, andelin_len_box) 1099 var cert_andelin_len: i64 = andelin_len_box[0] 1100 var ecdsa_andelin: *u8 = sd2_load_key(NX_SD2_PRIV_ANDELIN) 1101 var andelin_src: i64 = 1 1102 if (cert_andelin as i64) == 0 { andelin_src = 0 } 1103 if (ecdsa_andelin as i64) == 0 { andelin_src = 0 } 1104 if andelin_src == 0 { 1105 cert_andelin = cert_nishi 1106 cert_andelin_len = cert_nishi_len 1107 ecdsa_andelin = ecdsa_nishi 1108 } 1109 1110 // ---- DATA-DRIVEN cert table: load the manifest (row 0 = default). Fall back to the legacy 1111 // nishi+andelin pair if the manifest is absent/empty so nothing regresses (rule 20 fail-safe). ---- 1112 let cert_suf_ptrs: *i64 = (sys_mmap(NX_SD2_CERT_MAX * 8)) as *i64 1113 let cert_suf_lens: *i64 = (sys_mmap(NX_SD2_CERT_MAX * 8)) as *i64 1114 let cert_buf_ptrs: *i64 = (sys_mmap(NX_SD2_CERT_MAX * 8)) as *i64 1115 let cert_buf_lens: *i64 = (sys_mmap(NX_SD2_CERT_MAX * 8)) as *i64 1116 let cert_key_ptrs: *i64 = (sys_mmap(NX_SD2_CERT_MAX * 8)) as *i64 1117 let man_box: *i64 = (sys_mmap(8)) as *i64 1118 man_box[0] = 0 1119 let man_buf: *u8 = sys_read_file(NX_SD2_CERT_MANIFEST, man_box) 1120 var cert_count: i64 = 0 1121 if (man_buf as i64) != 0 { 1122 cert_count = sd2_load_cert_table(man_buf, man_box[0], cert_suf_ptrs, cert_suf_lens, cert_buf_ptrs, cert_buf_lens, cert_key_ptrs, NX_SD2_CERT_MAX) 1123 } 1124 if cert_count == 0 { 1125 cert_suf_ptrs[0] = ("nishifamily.com" as *u8) as i64 1126 cert_suf_lens[0] = 15 1127 cert_buf_ptrs[0] = cert_nishi as i64 1128 cert_buf_lens[0] = cert_nishi_len 1129 cert_key_ptrs[0] = ecdsa_nishi as i64 1130 cert_suf_ptrs[1] = ("andelinwest.com" as *u8) as i64 1131 cert_suf_lens[1] = 15 1132 cert_buf_ptrs[1] = cert_andelin as i64 1133 cert_buf_lens[1] = cert_andelin_len 1134 cert_key_ptrs[1] = ecdsa_andelin as i64 1135 cert_count = 2 1136 } 1137 sys_write(1, "nishi sites daemon v2: SNI cert table rows=" as *u8, 43) 1138 let ccb2: *u8 = sys_mmap(24) 1139 let ccn2: i64 = sd2_u64_to_dec(cert_count, ccb2) 1140 sys_write(1, ccb2, ccn2) 1141 sys_write(1, "\n" as *u8, 1) 1142 1143 let sd_cfg_box: *i64 = (sys_mmap(8)) as *i64 1144 sd_cfg_box[0] = 0 1145 var sites_cfg: *u8 = sys_read_file(NX_SD2_SITES_CONF, sd_cfg_box) 1146 var sites_cfg_n: i64 = 0 1147 if (sites_cfg as i64) != 0 { sites_cfg_n = sd_cfg_box[0] } 1148 // load the data-driven proxy route table (absent file -> proxy_cfg_n=0 -> legacy cascade only) 1149 let pr_cfg_box: *i64 = (sys_mmap(8)) as *i64 1150 pr_cfg_box[0] = 0 1151 var proxy_cfg: *u8 = sys_read_file(NX_SD2_PROXY_CONF, pr_cfg_box) 1152 var proxy_cfg_n: i64 = 0 1153 if (proxy_cfg as i64) != 0 { proxy_cfg_n = pr_cfg_box[0] } 1154 // load the data-driven ADNET inventory (absent -> adnet_cfg_n=0 -> slots OFF + no click route) 1155 let ad_cfg_box: *i64 = (sys_mmap(8)) as *i64 1156 ad_cfg_box[0] = 0 1157 let adnet_cfg: *u8 = sys_read_file(NX_SD2_ADNET_CONF, ad_cfg_box) 1158 var adnet_cfg_n: i64 = 0 1159 if (adnet_cfg as i64) != 0 { adnet_cfg_n = ad_cfg_box[0] } 1160 var ad_imp_fd: i64 = 0 - 1 1161 var ad_clk_fd: i64 = 0 - 1 1162 if adnet_cfg_n > 0 { ad_imp_fd = sys_openat_append(NX_SD2_ADNET_IMPLOG, 420) } 1163 if adnet_cfg_n > 0 { ad_clk_fd = sys_openat_append(NX_SD2_ADNET_CLKLOG, 420) } 1164 var ad_view_fd: i64 = 0 - 1 1165 if adnet_cfg_n > 0 { ad_view_fd = sys_openat_append(NX_SD2_ADNET_VIEWLOG, 420) } 1166 if adnet_cfg_n > 0 { 1167 let adr1: *u8 = "adnet: inventory loaded, slots ON\n" as *u8 1168 sys_write(1, adr1, sd2_strlen(adr1)) 1169 } else { 1170 let adr0: *u8 = "adnet: no inventory, slots OFF\n" as *u8 1171 sys_write(1, adr0, sd2_strlen(adr0)) 1172 } 1173 1174 let addr_buf: *u8 = sys_mmap(16) 1175 nx_http_server_addr_any(addr_buf, listen_port) 1176 let lv: *i64 = (sys_mmap(8)) as *i64 1177 let lfd: i64 = nx_http_server_listen(addr_buf, 16, lv) 1178 if lfd < 0 { return 4 } 1179 // ZOMBIE-REAP (2026-07-15): SO_RCVTIMEO on the listen socket -> accept() returns EAGAIN every 5s when 1180 // idle, so the wait4(WNOHANG) reap at the loop top runs promptly (not only when the next connection 1181 // arrives). Keeps the graceful fork-bomb cap intact; a real connection still returns immediately. 1182 sys_set_socket_timeout(lfd, 5) 1183 sys_write(1, "nishi sites daemon v2: vhosts + wss/video + circles on 0.0.0.0:8443\n" as *u8, 69) 1184 // Route B receipt: WHICH pair each domain serves (visible in sitetest / sites_run.log). 1185 if nishi_src == 1 { sys_write(1, "sni-cert nishi=per-domain\n" as *u8, 26) } else { sys_write(1, "sni-cert nishi=generic\n" as *u8, 23) } 1186 if andelin_src == 1 { sys_write(1, "sni-cert andelin=per-domain\n" as *u8, 28) } else { sys_write(1, "sni-cert andelin=nishi-fallback\n" as *u8, 32) } 1187 1188 let ctype_html: *u8 = "text/html; charset=utf-8" as *u8 1189 let nb_andelin: i64 = sd2_strlen(BODY2_ANDELIN) 1190 let nb_wiki: i64 = sd2_strlen(BODY2_WIKI) 1191 let nb_family: i64 = sd2_strlen(BODY2_FAMILY) 1192 let resp_andelin: *u8 = sys_mmap(nb_andelin + NX_SD2_HDR_RESERVE) 1193 let resp_wiki: *u8 = sys_mmap(nb_wiki + NX_SD2_HDR_RESERVE) 1194 let resp_family: *u8 = sys_mmap(nb_family + NX_SD2_HDR_RESERVE) 1195 let n_andelin: i64 = sd2_build_resp(resp_andelin, ctype_html, BODY2_ANDELIN, nb_andelin) 1196 let n_wiki: i64 = sd2_build_resp(resp_wiki, ctype_html, BODY2_WIKI, nb_wiki) 1197 let n_family: i64 = sd2_build_resp(resp_family, ctype_html, BODY2_FAMILY, nb_family) 1198 let n_favicon: i64 = sd2_strlen(RESP2_FAVICON) 1199 1200 var resp_wstatus: *u8 = sys_mmap(NX_SD2_STATUS_CAP) 1201 let wstatus_box: *i64 = (sys_mmap(8)) as *i64 1202 wstatus_box[0] = 0 1203 let wstatus_rc: i64 = nx_wiki_status_handle(resp_wstatus, NX_SD2_STATUS_CAP, wstatus_box) 1204 var n_wstatus: i64 = wstatus_box[0] 1205 if wstatus_rc != 0 { resp_wstatus = resp_wiki; n_wstatus = n_wiki } 1206 if n_wstatus <= 0 { resp_wstatus = resp_wiki; n_wstatus = n_wiki } 1207 1208 var resp_art_crawler: *u8 = sys_mmap(NX_SD2_ART_CAP) 1209 let acr_box: *i64 = (sys_mmap(8)) as *i64 1210 acr_box[0] = 0 1211 let acr_rc: i64 = nx_wiki_article_handle("crawler" as *u8, 7, resp_art_crawler, NX_SD2_ART_CAP, acr_box) 1212 var n_art_crawler: i64 = acr_box[0] 1213 if acr_rc != 0 { resp_art_crawler = resp_wiki; n_art_crawler = n_wiki } 1214 if n_art_crawler <= 0 { resp_art_crawler = resp_wiki; n_art_crawler = n_wiki } 1215 1216 var resp_art_x25519: *u8 = sys_mmap(NX_SD2_ART_CAP) 1217 let axx_box: *i64 = (sys_mmap(8)) as *i64 1218 axx_box[0] = 0 1219 let axx_rc: i64 = nx_wiki_article_handle("x25519" as *u8, 6, resp_art_x25519, NX_SD2_ART_CAP, axx_box) 1220 var n_art_x25519: i64 = axx_box[0] 1221 if axx_rc != 0 { resp_art_x25519 = resp_wiki; n_art_x25519 = n_wiki } 1222 if n_art_x25519 <= 0 { resp_art_x25519 = resp_wiki; n_art_x25519 = n_wiki } 1223 1224 var resp_art_ranking: *u8 = sys_mmap(NX_SD2_ART_CAP) 1225 let ark_box: *i64 = (sys_mmap(8)) as *i64 1226 ark_box[0] = 0 1227 let ark_rc: i64 = nx_wiki_article_handle("ranking-math" as *u8, 12, resp_art_ranking, NX_SD2_ART_CAP, ark_box) 1228 var n_art_ranking: i64 = ark_box[0] 1229 if ark_rc != 0 { resp_art_ranking = resp_wiki; n_art_ranking = n_wiki } 1230 if n_art_ranking <= 0 { resp_art_ranking = resp_wiki; n_art_ranking = n_wiki } 1231 1232 var resp_art_wiki: *u8 = sys_mmap(NX_SD2_ART_CAP) 1233 let awe_box: *i64 = (sys_mmap(8)) as *i64 1234 awe_box[0] = 0 1235 let awe_rc: i64 = nx_wiki_article_handle("wiki-engine" as *u8, 11, resp_art_wiki, NX_SD2_ART_CAP, awe_box) 1236 var n_art_wiki: i64 = awe_box[0] 1237 if awe_rc != 0 { resp_art_wiki = resp_wiki; n_art_wiki = n_wiki } 1238 if n_art_wiki <= 0 { resp_art_wiki = resp_wiki; n_art_wiki = n_wiki } 1239 1240 var resp_components: *u8 = sys_mmap(NX_SD2_ART_CAP) 1241 let aci_box: *i64 = (sys_mmap(8)) as *i64 1242 aci_box[0] = 0 1243 let aci_rc: i64 = nx_wiki_components_handle(resp_components, NX_SD2_ART_CAP, aci_box) 1244 var n_components: i64 = aci_box[0] 1245 if aci_rc != 0 { resp_components = resp_wiki; n_components = n_wiki } 1246 if n_components <= 0 { resp_components = resp_wiki; n_components = n_wiki } 1247 1248 var resp_projects: *u8 = resp_wiki 1249 var n_projects: i64 = n_wiki 1250 1251 // CONSTANT MEMORY: hoisted per-connection buffers (see v1 rationale). 1252 let server_random: *u8 = sys_mmap(32) 1253 let server_x25519_priv: *u8 = sys_mmap(32) 1254 let rec_buf: *u8 = sys_mmap(NX_SD2_RECCAP) 1255 let plain: *u8 = sys_mmap(NX_SD2_PLAINCAP) 1256 let out_rec: *u8 = sys_mmap(NX_SD2_OUTREC) 1257 let pump: *u8 = sys_mmap(NX_SD2_RECCAP) 1258 let dyn_buf: *u8 = sys_mmap(NX_SD2_DYN_CAP) 1259 let sock_addr: *u8 = sys_mmap(64) 1260 let sock_len: *i64 = (sys_mmap(8)) as *i64 1261 let tel_buf: *u8 = sys_mmap(256) 1262 let tel_fd: i64 = sys_openat_append(NX_SD2_TELEMETRY_PATH, 420) 1263 // Route B: hoisted SNI-peek buffers (constant memory; children get a COW copy on write). 1264 let sni_peek: *u8 = sys_mmap(NX_SD2_SNI_PEEK_CAP) 1265 let sni_host: *u8 = sys_mmap(256) 1266 1267 sys_set_socket_timeout(lfd, 5) 1268 let reap_status: *i64 = (sys_mmap(8)) as *i64 1269 var served: i64 = 0 1270 var live: i64 = 0 1271 1272 // ---- HOT-RELOAD (2026-07-15): config changes go LIVE on the NEXT CONNECTION, no restart. On each 1273 // accepted connection the PARENT (single-threaded between accepts; forked children snapshot a 1274 // consistent copy) compares (mtime,size) of cert-manifest / sites.conf / proxy_routes.conf and 1275 // re-reads on change. The cert table loads into TEMP arrays and copies over ONLY on a non-empty 1276 // parse, so a half-written/broken manifest can never wipe the live table (fail-safe, rule 14/20). 1277 let hr_statb: *u8 = sys_mmap(160) 1278 let hr_sig: *i64 = (sys_mmap(16)) as *i64 1279 var man_mt: i64 = 0 - 1 1280 var man_sz: i64 = 0 - 1 1281 if sd2_statsig(NX_SD2_CERT_MANIFEST, hr_statb, hr_sig) == 0 { man_mt = hr_sig[0]; man_sz = hr_sig[1] } 1282 var sc_mt: i64 = 0 - 1 1283 var sc_sz: i64 = 0 - 1 1284 if sd2_statsig(NX_SD2_SITES_CONF, hr_statb, hr_sig) == 0 { sc_mt = hr_sig[0]; sc_sz = hr_sig[1] } 1285 var prc_mt: i64 = 0 - 1 1286 var prc_sz: i64 = 0 - 1 1287 if sd2_statsig(NX_SD2_PROXY_CONF, hr_statb, hr_sig) == 0 { prc_mt = hr_sig[0]; prc_sz = hr_sig[1] } 1288 let tmp_suf_ptrs: *i64 = (sys_mmap(NX_SD2_CERT_MAX * 8)) as *i64 1289 let tmp_suf_lens: *i64 = (sys_mmap(NX_SD2_CERT_MAX * 8)) as *i64 1290 let tmp_buf_ptrs: *i64 = (sys_mmap(NX_SD2_CERT_MAX * 8)) as *i64 1291 let tmp_buf_lens: *i64 = (sys_mmap(NX_SD2_CERT_MAX * 8)) as *i64 1292 let tmp_key_ptrs: *i64 = (sys_mmap(NX_SD2_CERT_MAX * 8)) as *i64 1293 1294 while served < NX_SD2_BUDGET { 1295 while sys_wait4(0 - 1, reap_status, 1) > 0 { live = live - 1 } 1296 1297 sock_len[0] = 16 1298 let cfd: i64 = sys_accept_with_addr(lfd, sock_addr, sock_len) 1299 if cfd < 0 { continue } 1300 1301 // hot-reload check (parent, pre-fork): the connection just accepted already sees fresh config. 1302 if sd2_statsig(NX_SD2_CERT_MANIFEST, hr_statb, hr_sig) == 0 { 1303 if hr_sig[0] != man_mt || hr_sig[1] != man_sz { 1304 man_mt = hr_sig[0] 1305 man_sz = hr_sig[1] 1306 let mb2: *i64 = (sys_mmap(8)) as *i64 1307 mb2[0] = 0 1308 let mbuf2: *u8 = sys_read_file(NX_SD2_CERT_MANIFEST, mb2) 1309 if (mbuf2 as i64) != 0 { 1310 let nc2: i64 = sd2_load_cert_table(mbuf2, mb2[0], tmp_suf_ptrs, tmp_suf_lens, tmp_buf_ptrs, tmp_buf_lens, tmp_key_ptrs, NX_SD2_CERT_MAX) 1311 if nc2 > 0 { 1312 var ci2: i64 = 0 1313 while ci2 < nc2 { 1314 cert_suf_ptrs[ci2] = tmp_suf_ptrs[ci2] 1315 cert_suf_lens[ci2] = tmp_suf_lens[ci2] 1316 cert_buf_ptrs[ci2] = tmp_buf_ptrs[ci2] 1317 cert_buf_lens[ci2] = tmp_buf_lens[ci2] 1318 cert_key_ptrs[ci2] = tmp_key_ptrs[ci2] 1319 ci2 = ci2 + 1 1320 } 1321 cert_count = nc2 1322 sys_write(1, "hot-reload: cert table\n" as *u8, 23) 1323 } 1324 } 1325 } 1326 } 1327 if sd2_statsig(NX_SD2_SITES_CONF, hr_statb, hr_sig) == 0 { 1328 if hr_sig[0] != sc_mt || hr_sig[1] != sc_sz { 1329 sc_mt = hr_sig[0] 1330 sc_sz = hr_sig[1] 1331 let scb2: *i64 = (sys_mmap(8)) as *i64 1332 scb2[0] = 0 1333 let scfg2: *u8 = sys_read_file(NX_SD2_SITES_CONF, scb2) 1334 if (scfg2 as i64) != 0 { 1335 sites_cfg = scfg2 1336 sites_cfg_n = scb2[0] 1337 sys_write(1, "hot-reload: sites.conf\n" as *u8, 23) 1338 } 1339 } 1340 } 1341 if sd2_statsig(NX_SD2_PROXY_CONF, hr_statb, hr_sig) == 0 { 1342 if hr_sig[0] != prc_mt || hr_sig[1] != prc_sz { 1343 prc_mt = hr_sig[0] 1344 prc_sz = hr_sig[1] 1345 let pcb2: *i64 = (sys_mmap(8)) as *i64 1346 pcb2[0] = 0 1347 let pcfg2: *u8 = sys_read_file(NX_SD2_PROXY_CONF, pcb2) 1348 if (pcfg2 as i64) != 0 { 1349 proxy_cfg = pcfg2 1350 proxy_cfg_n = pcb2[0] 1351 sys_write(1, "hot-reload: proxy_routes.conf\n" as *u8, 30) 1352 } 1353 } 1354 } 1355 1356 if live >= NX_SD2_MAX_CHILDREN { 1357 if sys_wait4(0 - 1, reap_status, 0) > 0 { live = live - 1 } 1358 } 1359 1360 let pid: i64 = sys_fork() 1361 if pid == 0 { 1362 // ---- CHILD ---- 1363 sys_close(lfd) 1364 let acc_lan: i64 = nx_access_is_lan(sock_addr) 1365 sys_set_socket_timeout(cfd, 10) 1366 let nodelay: *u8 = sys_mmap(4) 1367 nodelay[0] = 1 as u8; nodelay[1] = 0 as u8; nodelay[2] = 0 as u8; nodelay[3] = 0 as u8 1368 sys_setsockopt(cfd, 6, 1, nodelay, 4) 1369 nx_csprng_fill(server_random, 32) 1370 nx_csprng_fill(server_x25519_priv, 32) 1371 // ---- Route B: SNI-aware cert selection ---- 1372 // MSG_PEEK the cleartext ClientHello (non-consuming), pick the per-domain wildcard 1373 // pair by the SNI, then run the UNCHANGED handshake serving that pair. Any peek 1374 // failure / absent / unknown SNI -> the default (nishifamily) pair. 1375 let pk_n: i64 = sys_recvfrom(cfd, sni_peek, NX_SD2_SNI_PEEK_CAP, NX_SD2_MSG_PEEK, 0 as *u8, 0 as *i64) 1376 // DATA-DRIVEN: pick the cert-table row from the SNI (row 0 = default; unknown/absent -> 0). 1377 var cert_idx: i64 = 0 1378 if pk_n > 0 { cert_idx = scs_pick_from_clienthello_table(sni_peek, pk_n, sni_host, 256, cert_suf_ptrs, cert_suf_lens, cert_count) } 1379 if cert_idx < 0 { cert_idx = 0 } 1380 if cert_idx >= cert_count { cert_idx = 0 } 1381 var use_cert: *u8 = cert_buf_ptrs[cert_idx] as *u8 1382 var use_cert_len: i64 = cert_buf_lens[cert_idx] 1383 var use_priv: *u8 = cert_key_ptrs[cert_idx] as *u8 1384 let t_hs0: i64 = sys_now_us() 1385 let hs_rc: i64 = nx_tls13_server_session_run( 1386 cfd, server_random, server_x25519_priv, 1387 use_cert, use_cert_len, use_priv) 1388 let hs_us: i64 = sys_now_us() - t_hs0 1389 // hs_rc carries TWO meanings: >0 it is a Tls13ServerSession HANDLE (cast below), <=0 it is a 1390 // failure status. Telemetry wants only the status. Passing the handle into a parameter named 1391 // `rc` conflated the two -- nx_telemetry_emit already had to defend itself with `if rc > 0 { rc = 0 }`, 1392 // which is the tell that a pointer was arriving where a status was declared. Narrow it ONCE, here, 1393 // so the serving path never hands an address to something that will report it as a number. 1394 var hs_stat: i64 = hs_rc 1395 if hs_stat > 0 { hs_stat = 0 } 1396 var vhost_id: i64 = 0 1397 var served_bytes: i64 = 0 1398 if hs_rc > 0 { 1399 let s: *Tls13ServerSession = hs_rc as *Tls13ServerSession 1400 var keep: i64 = 1 1401 var nreq: i64 = 0 1402 while keep == 1 { 1403 if nreq >= NX_SD2_MAX_REQ_PER_CONN { 1404 keep = 0 1405 } else { 1406 let plain_n: i64 = sd2_recv_request(s, cfd, rec_buf, plain, NX_SD2_PLAINCAP) 1407 let hdr_n: i64 = sd2_hdr_span(plain, plain_n) // seq1306: routes match HEADERS ONLY 1408 if plain_n <= 0 { 1409 keep = 0 1410 } else { 1411 // ---- D4: wss upgrade? consumes the connection ---- 1412 var is_ws: i64 = 0 1413 if sd2_contains(plain, hdr_n, "GET /signal/" as *u8, 12) == 1 { 1414 if sd2_contains_ci(plain, plain_n, "upgrade: websocket" as *u8, 18) == 1 { is_ws = 1 } 1415 if sd2_contains_ci(plain, plain_n, "upgrade:websocket" as *u8, 17) == 1 { is_ws = 1 } 1416 } 1417 if is_ws == 1 { 1418 vhost_id = 21 1419 sd2_ws_pump(s, cfd, plain, plain_n, rec_buf, out_rec, pump) 1420 keep = 0 1421 } else { 1422 var resp: *u8 = resp_family 1423 var resp_n: i64 = n_family 1424 let is_favicon: i64 = sd2_contains(plain, hdr_n, "favicon" as *u8, 7) 1425 if is_favicon == 1 { 1426 resp = RESP2_FAVICON; resp_n = n_favicon; vhost_id = 9 1427 } else { 1428 var dyn_done: i64 = 0 1429 // ---- DEBRIS REFUSAL (2026-07-30). Rollback/backup/temp artifacts sitting in a 1430 // docroot were being SERVED 200: measured https://andelinwest.com/index.html.bak-v1 1431 // returning a whole previous CLIENT homepage, plus 65 .prev/.bak/.nxw artifacts on 1432 // nishifamily. Every one is a public duplicate-content + information-disclosure 1433 // surface. Refused FIRST, before any handler can serve them, so the guarantee does 1434 // not depend on which route would have won. Path-bounded (hr_req_path), never a 1435 // whole-header scan -- a Referer carrying .bak must not 404 a real page. 1436 let dbz: *u8 = sys_mmap(NX_MAGIC_4096) 1437 let dbn: i64 = hr_req_path(plain, hdr_n, dbz, NX_MAGIC_4096) 1438 var dbg: i64 = 0 1439 if sd2_contains(dbz, dbn, ".prev" as *u8, 5) == 1 { dbg = 1 } 1440 if sd2_contains(dbz, dbn, ".bak" as *u8, 4) == 1 { dbg = 1 } 1441 if sd2_contains(dbz, dbn, ".nxw" as *u8, 4) == 1 { dbg = 1 } 1442 if sd2_contains(dbz, dbn, ".nxtmp" as *u8, 6) == 1 { dbg = 1 } 1443 if sd2_contains(dbz, dbn, ".nxpub" as *u8, 6) == 1 { dbg = 1 } 1444 if dbg == 1 { resp_n = hr_emit_404(dyn_buf, NX_SD2_DYN_CAP); resp = dyn_buf; vhost_id = 23; dyn_done = 1 } 1445 // ---- VIEWABLE-IMPRESSION BEACON: /ad/view/<id> (MRC 50pct for 1 continuous second). 1446 // Journalled SEPARATELY from served impressions so served/viewable stays a visible, 1447 // honest delivery ratio. FAIL-CLOSED: aview_resp only fills av_id for a well-formed 1448 // inventory id, so a forged or replayed path answers 204 and journals NOTHING. 1449 if dyn_done == 0 { if aview_is_path(dbz, dbn) == 1 { 1450 let av_id: *u8 = sys_mmap(128) 1451 let avr: i64 = aview_resp(dbz, dbn, dyn_buf, NX_SD2_DYN_CAP, av_id) 1452 if avr > 0 { 1453 resp = dyn_buf; resp_n = avr; vhost_id = 26; dyn_done = 1 1454 if ad_view_fd >= 0 { if av_id[0] != (0 as u8) { 1455 let avl: *u8 = sys_mmap(160) 1456 var avn: i64 = 0 1457 while av_id[avn] != (0 as u8) { avl[avn] = av_id[avn]; avn = avn + 1 } 1458 avl[avn] = 10 as u8 1459 avn = avn + 1 1460 sys_write(ad_view_fd, avl, avn) 1461 } } 1462 } 1463 } } 1464 // ---- HOT HOME: nishifamily root ("GET / HTTP") served from a LIVING FILE 1465 // (sites/nishifamily/home.html) so the front door updates via a file push, no 1466 // recompile -- the sovereign nav landing (nx_site_chrome home). NEVER-BRICK: 1467 // an absent/empty/unreadable file leaves dyn_done=0 -> the baked resp_family 1468 // (BODY2_FAMILY) serves EXACTLY as before. Guarded to nishifamily: skip if the 1469 // andelinwest host header is present (its root is served on its own vhost). 1470 if dyn_done == 0 { if sd2_contains(plain, hdr_n, "GET / HTTP" as *u8, 10) == 1 { 1471 // Nishifamily hot-home for the nishifamily apex + the DEFAULT (unknown) host ONLY. 1472 // Any OTHER registered vhost (andelinwest, b2b.loans, ...) skips this and serves its 1473 // OWN sites.conf docroot below -- data-driven, no per-domain hardcode. 1474 let hh_known: i64 = hr_known_host(sites_cfg, sites_cfg_n, plain, plain_n) 1475 let hh_nishi: i64 = sd2_contains(plain, hdr_n, "nishifamily" as *u8, 11) 1476 var hh_ok: i64 = 0 1477 if hh_known == 0 { hh_ok = 1 } 1478 else { if hh_nishi == 1 { hh_ok = 1 } } 1479 if hh_ok == 1 { 1480 let hm_box: *i64 = (sys_mmap(8)) as *i64; hm_box[0] = 0 1481 let hm_buf: *u8 = sys_read_file("/volume1/homes/elderwesto/nishihost/sites/nishifamily/home.html" as *u8, hm_box) 1482 if (hm_buf as i64) != 0 { if hm_box[0] > 0 { resp = dyn_buf; resp_n = sd2_build_resp(dyn_buf, ctype_html, hm_buf, hm_box[0]); vhost_id = 33; dyn_done = 1 } } 1483 } 1484 } } 1485 // ---- DATA-DRIVEN PROXY ROUTES (nx_proxy_route): app routes are CONFIG ROWS, no 1486 // recompile. Matched BEFORE the legacy hardcoded cascade. ADDITIVE + SAFE: no match 1487 // (or proxy_routes.conf absent -> proxy_cfg_n=0) leaves dyn_done=0 -> the legacy 1488 // cascade serves exactly as before. mode buffered(0)=sd2_proxy_to, stream(1)= 1489 // sd2_proxy_stream, gated(2)=proxy + fail-closed 302 /login. Same ports/semantics as 1490 // the cascade -> a config "match" is byte-identical to the hardcoded route it shadows. 1491 if dyn_done == 0 { if proxy_cfg_n > 0 { 1492 let pr_host: *u8 = sys_mmap(256) 1493 let pr_path: *u8 = sys_mmap(NX_MAGIC_4096) 1494 let pr_hn: i64 = hr_req_host(plain, plain_n, pr_host, 256) 1495 let pr_pn: i64 = hr_req_path(plain, hdr_n, pr_path, NX_MAGIC_4096) 1496 let pr_portb: *i64 = (sys_mmap(8)) as *i64 1497 let pr_modeb: *i64 = (sys_mmap(8)) as *i64 1498 if pr_lookup(proxy_cfg, proxy_cfg_n, pr_host, pr_hn, pr_path, pr_pn, pr_portb, pr_modeb) == 1 { 1499 if pr_modeb[0] == 1 { 1500 let pst: i64 = sd2_proxy_stream(s, cfd, plain, plain_n, pr_portb[0], out_rec) 1501 if pst >= 0 { served_bytes = served_bytes + pst; resp_n = 0; vhost_id = 70; dyn_done = 1; keep = 0 } 1502 } else { 1503 // buffered/gated: complete the request body FIRST (sd2_fill_body; 1504 // fail-safe no-op for GETs/complete bodies) so >8KB POST chunks 1505 // reach the backend whole -- the API bulk-upload unlock. 1506 if sd2_content_length(plain, plain_n) > NX_SD2_PLAINCAP { 1507 resp = RESP2_413; resp_n = sd2_strlen(RESP2_413); vhost_id = 13; dyn_done = 1; keep = 0 1508 } else { 1509 let pfn: i64 = sd2_fill_body(s, cfd, rec_buf, plain, plain_n, NX_SD2_PLAINCAP) 1510 let pbr: i64 = sd2_proxy_to(plain, pfn, dyn_buf, pr_portb[0]) 1511 if pbr > 0 { resp = dyn_buf; resp_n = pbr; vhost_id = 70; dyn_done = 1 } 1512 else { if pr_modeb[0] == 2 { resp = RESP2_GATE_LOGIN; resp_n = sd2_strlen(RESP2_GATE_LOGIN); vhost_id = 70; dyn_done = 1 } else { 1513 // seq1294 (both edge outages, 07-20 + 07-29): a PROXIED route whose backend 1514 // yielded NO bytes is an ERROR -- falling through to the static cascade served 1515 // the HOMEPAGE as a 200, and that HTML-to-a-machine-client is the retry-storm 1516 // trigger. Content-negotiated honest 503 + Retry-After instead: machines (no 1517 // text/html in Accept) get RFC-9457 problem+json; browsers get a real 503 page. 1518 var e_w: i64 = 0 1519 if sd2_contains(plain, hdr_n, "text/html" as *u8, 9) == 1 { 1520 let eb: *u8 = "<!doctype html><h1>503 backend unavailable</h1><p>The service behind this route did not answer inside the edge window. Retry shortly.</p>" as *u8 1521 e_w = hr_emit_b(dyn_buf, NX_SD2_DYN_CAP, "HTTP/1.1 503 Service Unavailable\r\nRetry-After: 5" as *u8, "text/html; charset=utf-8" as *u8, eb, sd2_strlen(eb)) 1522 } else { 1523 let ej: *u8 = "{\"type\":\"about:blank\",\"title\":\"Service Unavailable\",\"status\":503,\"detail\":\"upstream backend gave no response inside the edge window; retry after 5s\"}" as *u8 1524 e_w = hr_emit_b(dyn_buf, NX_SD2_DYN_CAP, "HTTP/1.1 503 Service Unavailable\r\nRetry-After: 5" as *u8, "application/problem+json" as *u8, ej, sd2_strlen(ej)) 1525 } 1526 if e_w > 0 { resp = dyn_buf; resp_n = e_w; vhost_id = 71; dyn_done = 1; keep = 0 } 1527 } } 1528 } 1529 } 1530 } 1531 } } 1532 // ---- ADNET first-party click redirect (/ad/click/<id>) + per-AD click counter. 1533 // No visitor id/cookie ever; unknown/invalid id -> 302 / (fail-closed). Only alive 1534 // when the inventory conf exists (adnet_cfg_n>0) -> zero behavior change otherwise. 1535 if dyn_done == 0 { if adnet_cfg_n > 0 { 1536 if sd2_contains(plain, hdr_n, "GET /ad/click/" as *u8, 14) == 1 { 1537 let ac_path: *u8 = sys_mmap(NX_MAGIC_4096) 1538 let ac_pn: i64 = hr_req_path(plain, hdr_n, ac_path, NX_MAGIC_4096) 1539 let ac_id: *u8 = sys_mmap(128) 1540 let ac_w: i64 = aslot_click_resp(adnet_cfg, adnet_cfg_n, ac_path, ac_pn, dyn_buf, NX_SD2_DYN_CAP, ac_id) 1541 if ac_w > 0 { 1542 resp = dyn_buf; resp_n = ac_w; vhost_id = 28; dyn_done = 1 1543 if ad_clk_fd >= 0 { if ac_id[0] != (0 as u8) { 1544 let ac_line: *u8 = sys_mmap(160) 1545 var ac_ln: i64 = 0 1546 while ac_id[ac_ln] != (0 as u8) { ac_line[ac_ln] = ac_id[ac_ln]; ac_ln = ac_ln + 1 } 1547 ac_line[ac_ln] = 10 as u8 1548 ac_ln = ac_ln + 1 1549 sys_write(ad_clk_fd, ac_line, ac_ln) 1550 } } 1551 } 1552 } 1553 } } 1554 // ---- ADNET public aggregate dashboard (/ad/dash): per-AD served/click counters 1555 // rendered LIVE from the append-only logs each request (BOUNDED reads, rule 21). 1556 // Aggregate-only by construction (logs carry ad ids, never visitor identity) -> 1557 // public transparency is safe; the page self-opts-out of slot injection. 1558 if dyn_done == 0 { if adnet_cfg_n > 0 { 1559 if sd2_contains(plain, hdr_n, "GET /ad/dash" as *u8, 12) == 1 { 1560 let dd_il: *u8 = sys_mmap(NX_MAGIC_1048576) 1561 let dd_iln: i64 = and_read_bounded(NX_SD2_ADNET_IMPLOG, dd_il, NX_MAGIC_1048576) 1562 let dd_cl: *u8 = sys_mmap(NX_MAGIC_1048576) 1563 let dd_cln: i64 = and_read_bounded(NX_SD2_ADNET_CLKLOG, dd_cl, NX_MAGIC_1048576) 1564 let dd_page: *u8 = sys_mmap(NX_MAGIC_262144) 1565 let dd_pn: i64 = and_page(adnet_cfg, adnet_cfg_n, dd_il, dd_iln, dd_cl, dd_cln, dd_page, NX_MAGIC_262144) 1566 if dd_pn > 0 { 1567 let dd_w: i64 = hr_emit_b(dyn_buf, NX_SD2_DYN_CAP, "HTTP/1.1 200 OK" as *u8, "text/html; charset=utf-8" as *u8, dd_page, dd_pn) 1568 if dd_w > 0 { resp = dyn_buf; resp_n = dd_w; vhost_id = 29; dyn_done = 1 } 1569 } 1570 } 1571 } } 1572 // ---- SELF-SERVE advertiser intake (/ad/submit): GET renders the zero-JS form, 1573 // POST validates (fail-closed, same validators as serving) + stages to a NON-public 1574 // operator-review journal (nishihost/adnet_submissions.log). STAGED IS NOT LIVE. 1575 if dyn_done == 0 { if adnet_cfg_n > 0 { 1576 if sd2_contains(plain, hdr_n, " /ad/submit" as *u8, 11) == 1 { 1577 let su_page: *u8 = sys_mmap(NX_MAGIC_131072) 1578 var su_pn: i64 = 0 1579 if sd2_contains(plain, hdr_n, "POST /ad/submit" as *u8, 15) == 1 { 1580 let su_bs: i64 = sd2_body_start(plain, plain_n) 1581 let su_body: *u8 = ((plain as i64) + su_bs) as *u8 1582 let su_bn: i64 = plain_n - su_bs 1583 su_pn = asf_post(su_body, su_bn, "adnet_submissions.log" as *u8, su_page, NX_MAGIC_131072) 1584 } else { 1585 su_pn = asf_form_page(su_page, NX_MAGIC_131072) 1586 } 1587 if su_pn > 0 { 1588 let su_w: i64 = hr_emit_b(dyn_buf, NX_SD2_DYN_CAP, "HTTP/1.1 200 OK" as *u8, "text/html; charset=utf-8" as *u8, su_page, su_pn) 1589 if su_w > 0 { resp = dyn_buf; resp_n = su_w; vhost_id = 31; dyn_done = 1 } 1590 } 1591 } 1592 } } 1593 // RACI: /video is OWNED solely by hr_resolve (clean URL -> video/index.html), 1594 // exactly like /games. The old bare-/video -> 301 /video/ rule here was a SECOND, 1595 // competing owner; colliding with the file server's slash handling it produced 1596 // "too many redirects". Removed per the single-owner principle -> /video falls 1597 // through to the file server (hr_serve2), which serves video/index.html directly. 1598 // /advertising (top-level, operator-only) -> 301 to the OPAQUE-gated census page 1599 if dyn_done == 0 { if sd2_contains(plain, hdr_n, "GET /advertising HTTP" as *u8, 21) == 1 { 1600 resp = RESP2_ADV_301; resp_n = sd2_strlen(RESP2_ADV_301); vhost_id = 26; dyn_done = 1 1601 } } 1602 // bare /status and /status/ -> /status.html (the live supervisor-emitted dashboard). 1603 // "GET /status HTTP"(16) matches ONLY exact /status (not /status.html -> ".html"!=" "). 1604 if dyn_done == 0 { if sd2_contains(plain, hdr_n, "GET /status HTTP" as *u8, 16) == 1 { 1605 resp = RESP2_STATUS_301; resp_n = sd2_strlen(RESP2_STATUS_301); vhost_id = 27; dyn_done = 1 1606 } } 1607 if dyn_done == 0 { if sd2_contains(plain, hdr_n, "GET /status/ HTTP" as *u8, 17) == 1 { 1608 resp = RESP2_STATUS_301; resp_n = sd2_strlen(RESP2_STATUS_301); vhost_id = 27; dyn_done = 1 1609 } } 1610 // ---- OPAQUE no-cookie login (sovereign): reverse-proxy /login,/register, 1611 // /whoami,/audio to the loopback login daemon (127.0.0.1:9091). This serves 1612 // nishifamily.com/login from the Nishi substrate itself -- NO nginx, NO third 1613 // party. ADDITIVE: a proxy miss leaves dyn_done=0 -> normal routing serves. 1614 if dyn_done == 0 { if sd2_is_login_route(plain, hdr_n) == 1 { 1615 let lpr: i64 = sd2_proxy_to(plain, plain_n, dyn_buf, NX_MAGIC_9091) 1616 if lpr > 0 { resp = dyn_buf; resp_n = lpr; vhost_id = 50; dyn_done = 1 } 1617 } } 1618 // ---- GALLERY (OPAQUE-gated, NSFW): reverse-proxy /gallery -> bridge 1619 // (127.0.0.1:18190) -> reverse-tunnel -> workstation gateway:18091 (OPAQUE 1620 // session check) -> gallery:18090. ADDITIVE: a proxy miss (bridge down) 1621 // leaves dyn_done=0 -> normal routing serves; /gallery is never a public byte 1622 // unless the OPAQUE gateway authorized it. 1623 if dyn_done == 0 { if sd2_contains(plain, hdr_n, " /gallery" as *u8, 9) == 1 { 1624 // STREAM /gallery (large video + images) chunk-by-chunk to the client -- 1625 // NO 8MB dyn_buf cap, NO buffer-then-send latency. gst>=0 => already sent 1626 // (resp_n=0 skips the buffered D1 send); gst<0 => backend down, fall through. 1627 let gst: i64 = sd2_proxy_stream(s, cfd, plain, plain_n, NX_MAGIC_18190, out_rec) 1628 if gst >= 0 { served_bytes = served_bytes + gst; resp_n = 0; vhost_id = 60; dyn_done = 1; keep = 0 } 1629 } } 1630 // ---- WIKI (OPAQUE-gated, Nishi Family): reverse-proxy /wiki -> the wiki 1631 // gateway (127.0.0.1:18791; OPAQUE session check, no session -> login page). 1632 // ADDITIVE: a proxy miss (gateway down) leaves dyn_done=0 -> normal routing serves. 1633 if dyn_done == 0 { if sd2_wiki_gated(plain, hdr_n) == 1 { 1634 // no-cookie redirect fix: a TOP-LEVEL nav (Accept: text/html, NO X-Nishi-Session) gets the 1635 // return-aware bootstrap, not the wiki gateway's stale board()->hub login. Session-fetches + 1636 // assets (no text/html) still proxy unchanged -> no asset/content regression. 1637 var wiki_done: i64 = 0 1638 if sd2_contains(plain, hdr_n, "X-Nishi-Session" as *u8, 15) == 0 { if sd2_contains(plain, hdr_n, "text/html" as *u8, 9) == 1 { 1639 resp = dyn_buf; resp_n = sd2_build_resp(dyn_buf, ctype_html, BODY2_WIKI_BOOTSTRAP, sd2_strlen(BODY2_WIKI_BOOTSTRAP)); vhost_id = 61; dyn_done = 1; wiki_done = 1 1640 } } 1641 if wiki_done == 0 { 1642 let wgpr: i64 = sd2_proxy_to(plain, plain_n, dyn_buf, NX_MAGIC_18791) 1643 if wgpr > 0 { resp = dyn_buf; resp_n = wgpr; vhost_id = 61; dyn_done = 1 } 1644 else { resp = RESP2_GATE_LOGIN; resp_n = sd2_strlen(RESP2_GATE_LOGIN); vhost_id = 61; dyn_done = 1 } 1645 } 1646 } } 1647 // ---- HUB (OPAQUE-gated, maturity-flag leveled): reverse-proxy /hub -> the hub gateway 1648 // (127.0.0.1:18792; mr_route over the maturity registry; OPAQUE session -> level). 1649 // FAIL-CLOSED: a proxy miss -> 302 /login (never a public byte), mirroring /wiki. 1650 if dyn_done == 0 { if sd2_contains(plain, hdr_n, " /hub" as *u8, 5) == 1 { 1651 let hgpr: i64 = sd2_proxy_to(plain, plain_n, dyn_buf, NX_MAGIC_18792) 1652 if hgpr > 0 { resp = dyn_buf; resp_n = hgpr; vhost_id = 62; dyn_done = 1 } 1653 else { resp = RESP2_GATE_LOGIN; resp_n = sd2_strlen(RESP2_GATE_LOGIN); vhost_id = 62; dyn_done = 1 } 1654 } } 1655 // ---- GEN (Elder AI image generation, OPAQUE-gated owner): reverse-proxy /gen -> 1656 // the gen gateway (127.0.0.1:18794; family OPAQUE session + he_has_access(/gen) -> 1657 // orchestrator :18795 -> laptop 5080). FAIL-CLOSED: a proxy miss (gateway down) -> 1658 // 302 /login (never a public byte), mirroring /wiki,/hub. ADDITIVE: the leading-space 1659 // " /gen" matches only the request-line path, never a header, so other sites are untouched. 1660 if dyn_done == 0 { if sd2_contains(plain, hdr_n, " /gen" as *u8, 5) == 1 { 1661 let ggpr: i64 = sd2_proxy_to(plain, plain_n, dyn_buf, NX_MAGIC_18794) 1662 if ggpr > 0 { resp = dyn_buf; resp_n = ggpr; vhost_id = 64; dyn_done = 1 } 1663 else { resp = RESP2_GATE_LOGIN; resp_n = sd2_strlen(RESP2_GATE_LOGIN); vhost_id = 64; dyn_done = 1 } 1664 } } 1665 // ---- TORRENT/MEDIA acquirer (OPAQUE-gated, owner): reverse-proxy /torrent -> the 1666 // torrent gateway (127.0.0.1:18793; OPAQUE session -> X-Nishi-Level:OWNER -> daemon :8097). 1667 // STREAMED (the acquirer serves video). ADDITIVE: a proxy miss leaves dyn_done=0 -> normal routing. 1668 if dyn_done == 0 { if sd2_contains(plain, hdr_n, " /torrent" as *u8, 9) == 1 { 1669 let tst: i64 = sd2_proxy_stream(s, cfd, plain, plain_n, NX_MAGIC_18793, out_rec) 1670 if tst >= 0 { served_bytes = served_bytes + tst; resp_n = 0; vhost_id = 63; dyn_done = 1 } 1671 } } 1672 // ---- STUDIO (OPAQUE-gated, operator-only): reverse-proxy /studio -> NAS-local 1673 // gated daemon (127.0.0.1:18099; OPAQUE session check, no token -> 401). ADDITIVE: 1674 // a proxy miss leaves dyn_done=0 -> normal routing serves; /studio is never a 1675 // public byte unless the OPAQUE gate authorized it. [[project-image-stack-ownership-2026-06-17]] 1676 if dyn_done == 0 { if sd2_contains(plain, hdr_n, " /studio" as *u8, 8) == 1 { 1677 let spr: i64 = sd2_proxy_to(plain, plain_n, dyn_buf, NX_MAGIC_18099) 1678 if spr > 0 { resp = dyn_buf; resp_n = spr; vhost_id = 61; dyn_done = 1 } 1679 } } 1680 // ---- LIBRARY (nishifamily.com/library): reverse-proxy /library -> the 1681 // auth-walled Calibre reader (127.0.0.1:8791, keeper-supervised). The reader 1682 // is /library-prefix-aware (input-strips /library, serves <base href=/library/>). 1683 // ADDITIVE: a proxy miss (reader down) leaves dyn_done=0 -> normal routing serves. 1684 if dyn_done == 0 { if sd2_contains(plain, hdr_n, " /library" as *u8, 9) == 1 { 1685 let lipr: i64 = sd2_proxy_to(plain, plain_n, dyn_buf, NX_MAGIC_8791) 1686 if lipr > 0 { resp = dyn_buf; resp_n = lipr; vhost_id = 61; dyn_done = 1 } 1687 } } 1688 // ---- MEDIA (nishifamily.com/media): the FAMILY-facing SFW library -> the SAME 1689 // auth-walled media reader (127.0.0.1:8791). The reader is /media-prefix-aware + 1690 // denies the owner-only /mnt/nas_logging (galx_media_path_ok) so family gets SFW 1691 // only; the owner-only recordings/NSFW are /gallery. ADDITIVE: a miss falls through. 1692 if dyn_done == 0 { if sd2_contains(plain, hdr_n, " /media" as *u8, 7) == 1 { 1693 let mepr: i64 = sd2_proxy_to(plain, plain_n, dyn_buf, NX_MAGIC_8791) 1694 if mepr > 0 { resp = dyn_buf; resp_n = mepr; vhost_id = 61; dyn_done = 1 } 1695 } } 1696 // ---- D5: circles ---- 1697 if sd2_contains(plain, hdr_n, "POST /video/circle?" as *u8, 19) == 1 { 1698 resp_n = sd2_circle_upload(s, cfd, plain, plain_n, rec_buf, pump, dyn_buf) 1699 resp = dyn_buf; vhost_id = 22; dyn_done = 1 1700 } 1701 if dyn_done == 0 { if sd2_contains(plain, hdr_n, "GET /video/circles" as *u8, 18) == 1 { 1702 resp_n = sd2_circle_list(plain, plain_n, dyn_buf) 1703 resp = dyn_buf; vhost_id = 23; dyn_done = 1 1704 } } 1705 if dyn_done == 0 { if sd2_contains(plain, hdr_n, "GET /video/circle/" as *u8, 18) == 1 { 1706 resp_n = sd2_circle_play(plain, plain_n, dyn_buf) 1707 resp = dyn_buf; vhost_id = 24; dyn_done = 1 1708 } } 1709 // ---- wiki dynamic routes (v1 behaviour) ---- 1710 if dyn_done == 0 { if sd2_contains(plain, hdr_n, "POST /wiki/request" as *u8, 18) == 1 { 1711 let bstart: i64 = sd2_body_start(plain, plain_n) 1712 let dnq: *i64 = (sys_mmap(8)) as *i64 1713 dnq[0] = 0 1714 let prc: i64 = nx_wiki_request_handle((plain as i64 + bstart) as *u8, plain_n - bstart, dyn_buf, NX_SD2_DYN_CAP, dnq) 1715 if prc == 0 { resp = dyn_buf; resp_n = dnq[0]; vhost_id = 10; dyn_done = 1 } 1716 } } 1717 if dyn_done == 0 { if sd2_contains(plain, hdr_n, "/wiki/queue" as *u8, 11) == 1 { 1718 let dnq2: *i64 = (sys_mmap(8)) as *i64 1719 dnq2[0] = 0 1720 let qrc: i64 = nx_wiki_queue_handle(dyn_buf, NX_SD2_DYN_CAP, dnq2) 1721 if qrc == 0 { resp = dyn_buf; resp_n = dnq2[0]; vhost_id = 11; dyn_done = 1 } 1722 } } 1723 // ---- D3: hot file hosting with fallthrough (+ universal ADNET slot injection). 1724 // adnet_cfg_n==0 OR host not @host-enabled -> slot_n=0 -> hr_serve3_slot is 1725 // BYTE-IDENTICAL to hr_serve3 (gated do-no-harm law) -> zero behavior change. 1726 if dyn_done == 0 { 1727 let nbox: *i64 = (sys_mmap(8)) as *i64 1728 var ad_slot_n: i64 = 0 1729 let ad_slotb: *u8 = sys_mmap(NX_MAGIC_8192) 1730 let ad_sid: *u8 = sys_mmap(128) 1731 let ad_injb: *i64 = (sys_mmap(8)) as *i64 1732 ad_injb[0] = 0 1733 if adnet_cfg_n > 0 { 1734 let ad_host: *u8 = sys_mmap(256) 1735 hr_req_host(plain, plain_n, ad_host, 256) 1736 let ad_hok: i64 = aslot_host_ok(adnet_cfg, adnet_cfg_n, ad_host) 1737 if ad_hok == 1 { 1738 let ad_path: *u8 = sys_mmap(NX_MAGIC_4096) 1739 let ad_pn: i64 = hr_req_path(plain, hdr_n, ad_path, NX_MAGIC_4096) 1740 let ad_now: i64 = sys_now_us() 1741 let ad_rot: i64 = ad_now / NX_SD2_ADNET_ROT_US 1742 ad_slot_n = aslot_html(adnet_cfg, adnet_cfg_n, ad_path, ad_pn, ad_rot, ad_slotb, NX_MAGIC_8192, ad_sid) 1743 // WIRE THE VIEWABILITY OBSERVER (debt 1785512185). Appended to the slot bytes BEFORE 1744 // hr_serve3_slot merges them, so Content-Length stays correct by construction. A refused 1745 // emit (bad id / no room) leaves ad_slot_n untouched -> the slot serves exactly as before. 1746 if ad_slot_n > 0 { if ad_sid[0] != (0 as u8) { 1747 let av_n: i64 = aview_script(((ad_slotb as i64) + ad_slot_n) as *u8, NX_MAGIC_8192 - ad_slot_n, ad_sid) 1748 if av_n > 0 { ad_slot_n = ad_slot_n + av_n } 1749 } } 1750 } 1751 } 1752 let sv: i64 = hr_serve3_slot(sites_cfg, sites_cfg_n, plain, plain_n, dyn_buf, NX_SD2_DYN_CAP, nbox, ad_slotb, ad_slot_n, ad_injb) 1753 if sv == HR_S2_OK { resp = dyn_buf; resp_n = nbox[0]; vhost_id = 20; dyn_done = 1 } 1754 if sv == HR_S2_OK { if ad_injb[0] == 1 { if ad_imp_fd >= 0 { if ad_sid[0] != (0 as u8) { 1755 let ai_line: *u8 = sys_mmap(160) 1756 var ai_ln: i64 = 0 1757 while ad_sid[ai_ln] != (0 as u8) { ai_line[ai_ln] = ad_sid[ai_ln]; ai_ln = ai_ln + 1 } 1758 ai_line[ai_ln] = 10 as u8 1759 ai_ln = ai_ln + 1 1760 sys_write(ad_imp_fd, ai_line, ai_ln) 1761 } } } } 1762 if sv == HR_S2_REDIR { resp = dyn_buf; resp_n = nbox[0]; vhost_id = 20; dyn_done = 1 } 1763 if sv == HR_S2_BAD { resp = dyn_buf; resp_n = nbox[0]; vhost_id = 20; dyn_done = 1 } 1764 if sv == HR_S2_TOOBIG { resp = dyn_buf; resp_n = nbox[0]; vhost_id = 20; dyn_done = 1 } 1765 if sv == HR_S2_STREAM { 1766 // ZERO-CEILING STREAM (debt 1785879638): headers then the oversize body through 1767 // the SAME chunked TLS send that carries every response -- no size constant on 1768 // this path; anything the host can mmap serves. Connection closes after (exact 1769 // Content-Length + close = valid HTTP; keep-alive resumes on the next connect). 1770 let sh: i64 = nx_tls13_app_send_fd(s, dyn_buf, nbox[0], cfd, out_rec, NX_SD2_OUTREC) 1771 if sh >= 0 { 1772 let sb: i64 = nx_tls13_app_send_fd(s, hr_stream_body() as *u8, hr_stream_bodyn(), cfd, out_rec, NX_SD2_OUTREC) 1773 if sb >= 0 { served_bytes = served_bytes + nbox[0] + hr_stream_bodyn(); nreq = nreq + 1 } 1774 } 1775 resp = dyn_buf 1776 resp_n = 0 1777 vhost_id = 20 1778 dyn_done = 1 1779 } 1780 // MISS on andelinwest = REAL 404 (its real site is file-based; 1781 // never bleed the family placeholder onto it) 1782 if sv == HR_S2_MISS { 1783 if sd2_contains(plain, hdr_n, "andelinwest" as *u8, 11) == 1 { 1784 if sd2_contains(plain, hdr_n, "GET / HTTP" as *u8, 10) == 0 { 1785 resp_n = hr_emit_404(dyn_buf, NX_SD2_DYN_CAP) 1786 resp = dyn_buf; vhost_id = 20; dyn_done = 1 1787 } 1788 } 1789 } 1790 } 1791 // ---- live wiki engine proxy (imported corpus + search) ---- 1792 // GET /wiki/<slug> that hr_serve2 MISSED, isn't a .html hot file, 1793 // and isn't a baked route -> reverse-proxy to the loopback wiki 1794 // engine (127.0.0.1:51850). ADDITIVE: on any failure dyn_done stays 1795 // 0 and the existing baked placeholder serves (never breaks the site). 1796 if dyn_done == 0 { 1797 if sd2_contains(plain, hdr_n, "GET /wiki/" as *u8, 10) == 1 { 1798 var wbaked: i64 = 0 1799 if sd2_contains(plain, hdr_n, ".html" as *u8, 5) == 1 { wbaked = 1 } 1800 if sd2_contains(plain, hdr_n, "/wiki/roadmap" as *u8, 13) == 1 { wbaked = 1 } 1801 if sd2_contains(plain, hdr_n, "/wiki/status" as *u8, 12) == 1 { wbaked = 1 } 1802 if sd2_contains(plain, hdr_n, "/wiki/components" as *u8, 16) == 1 { wbaked = 1 } 1803 if sd2_contains(plain, hdr_n, "/wiki/component/" as *u8, 16) == 1 { wbaked = 1 } 1804 if sd2_contains(plain, hdr_n, "/wiki/projects" as *u8, 14) == 1 { wbaked = 1 } 1805 if sd2_contains(plain, hdr_n, "/wiki/request" as *u8, 13) == 1 { wbaked = 1 } 1806 if sd2_contains(plain, hdr_n, "/wiki/queue" as *u8, 11) == 1 { wbaked = 1 } 1807 if wbaked == 0 { 1808 let wpr: i64 = sd2_wiki_proxy(plain, plain_n, dyn_buf) 1809 if wpr > 0 { resp = dyn_buf; resp_n = wpr; vhost_id = 40; dyn_done = 1 } 1810 } 1811 } 1812 } 1813 // ---- legacy hot roadmap + baked routes (v1) ---- 1814 if dyn_done == 0 { 1815 if sd2_contains(plain, hdr_n, "/wiki/roadmap" as *u8, 13) == 1 { 1816 let rlb: *i64 = (sys_mmap(8)) as *i64 1817 rlb[0] = 0 1818 let rbuf: *u8 = sys_read_file("/volume1/homes/elderwesto/nishihost/wiki/roadmap.html" as *u8, rlb) 1819 if (rbuf as i64) != 0 { resp = dyn_buf; resp_n = sd2_build_resp(dyn_buf, ctype_html, rbuf, rlb[0]); vhost_id = 30; dyn_done = 1 } 1820 } 1821 } 1822 if dyn_done == 0 { 1823 let is_andelin: i64 = sd2_contains(plain, hdr_n, "andelinwest" as *u8, 11) 1824 let is_wiki: i64 = sd2_contains(plain, hdr_n, "/wiki" as *u8, 5) 1825 let is_wstatus: i64 = sd2_contains(plain, hdr_n, "/wiki/status" as *u8, 12) 1826 let is_cidx: i64 = sd2_contains(plain, hdr_n, "/wiki/components" as *u8, 16) 1827 let is_proj: i64 = sd2_contains(plain, hdr_n, "/wiki/projects" as *u8, 14) 1828 let is_cr: i64 = sd2_contains(plain, hdr_n, "/wiki/component/crawler" as *u8, 23) 1829 let is_xx: i64 = sd2_contains(plain, hdr_n, "/wiki/component/x25519" as *u8, 22) 1830 let is_rk: i64 = sd2_contains(plain, hdr_n, "/wiki/component/ranking-math" as *u8, 28) 1831 let is_we: i64 = sd2_contains(plain, hdr_n, "/wiki/component/wiki-engine" as *u8, 27) 1832 if is_andelin == 1 { 1833 resp = resp_andelin; resp_n = n_andelin; vhost_id = 1 1834 } else { 1835 if is_wiki == 1 { resp = resp_wiki; resp_n = n_wiki; vhost_id = 2 } 1836 if is_wstatus == 1 { resp = resp_wstatus; resp_n = n_wstatus; vhost_id = 3 } 1837 if is_cidx == 1 { resp = resp_components; resp_n = n_components; vhost_id = 8 } 1838 if is_proj == 1 { resp = resp_projects; resp_n = n_projects; vhost_id = 12 } 1839 if is_cr == 1 { resp = resp_art_crawler; resp_n = n_art_crawler; vhost_id = 4 } 1840 if is_xx == 1 { resp = resp_art_x25519; resp_n = n_art_x25519; vhost_id = 5 } 1841 if is_rk == 1 { resp = resp_art_ranking; resp_n = n_art_ranking; vhost_id = 6 } 1842 if is_we == 1 { resp = resp_art_wiki; resp_n = n_art_wiki; vhost_id = 7 } 1843 } 1844 } 1845 } 1846 // ---- SOFT-404 ROOT FIX (2026-07-30) ------------------------------------------ 1847 // MEASURED: GET /zzz-not-a-page-12345 on nishifamily.com returned 200 with the 1848 // baked 835-byte family stub. Every unmatched path did. That burns crawl budget on 1849 // infinite phantom URLs AND makes a publishing-registry status of `withdrawn` 1850 // structurally unenforceable -- the page keeps answering 200 forever. 1851 // The test is `resp is STILL the family stub`, not `dyn_done == 0`: the baked-route 1852 // block below assigns resp WITHOUT setting dyn_done, so keying on dyn_done would 1853 // 404 legitimately-served pages. Pointer identity is exact -- the ONLY state that 1854 // changes is `nothing matched at all, for a non-root path`. 1855 // The root keeps the stub: that is the never-brick fallback for an absent home.html. 1856 if (resp as i64) == (resp_family as i64) { 1857 if sd2_contains(plain, hdr_n, "GET / HTTP" as *u8, 10) == 0 { 1858 resp_n = hr_emit_404(dyn_buf, NX_SD2_DYN_CAP) 1859 resp = dyn_buf 1860 vhost_id = 22 1861 } 1862 } 1863 // ---- D1: chunked send (any size up to DYN_CAP) ---- 1864 if resp_n > 0 { 1865 let sent: i64 = nx_tls13_app_send_fd(s, resp, resp_n, cfd, out_rec, NX_SD2_OUTREC) 1866 if sent < 0 { keep = 0 } 1867 else { served_bytes = served_bytes + resp_n; nreq = nreq + 1; sys_set_socket_timeout(cfd, NX_SD2_KA_IDLE_S) } 1868 } else { keep = 0 } 1869 } 1870 } 1871 } 1872 } 1873 } 1874 sys_close(cfd) 1875 nx_telemetry_emit(tel_fd, tel_buf, sys_now_us(), acc_lan, vhost_id, 1876 hs_us, served_bytes, hs_stat) 1877 sys_exit(0) 1878 } 1879 1880 sys_close(cfd) 1881 if pid > 0 { live = live + 1 } 1882 served = served + 1 1883 } 1884 sys_close(lfd) 1885 return 0 1886}