code wiki / _hdl_build / nx_site_handler.nx

nx_site_handler.nx source

↩ module page · 80 lines · 4701 B

1// nx_site_handler.nx -- the RECONCILED daemon's REQUEST HANDLER (bytes-in -> bytes-out, the part the TLS shell 2// wraps). Parses the decrypted HTTP request (Host + path), runs the data-driven decision (rt_match route / sd_vhost 3// docroot), and EITHER serves the vhost's docroot file (STATIC 200, or 404 if missing) OR signals the transport to 4// PROXY (port+mode -- the streaming relay is the io layer's job). NO hardcoded routes/hosts. The cert was already 5// chosen by the transport at handshake time (SNI -> cr_match), so the handler is route/static only. The gate drives 6// this IN-PROCESS (craft request bytes -> assert response/decision), no TLS/socket. Composes nx_site_dispatch 7// (rt_match + sd_vhost). license_tier: ORIGINAL 8import "nx_site_dispatch.nx" 9const SH_MAGIC_4096: i64 = 4096 10const SH_MAGIC_2048: i64 = 2048 11 12const SH_PROXY: i64 = 0 // dec[1]=port dec[2]=mode -> transport relays (out_n returned 0) 13const SH_STATIC: i64 = 1 // out holds a full 200 response (docroot file) 14const SH_NOTFOUND: i64 = 2 // out holds a full 404 response 15 16func sh_cat(d: *u8, o: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){d[o]=s[i];o=o+1;i=i+1} return o } 17func sh_catb(d: *u8, o: i64, b: *u8, n: i64) -> i64 { var i: i64=0; while i<n {d[o]=b[i];o=o+1;i=i+1} return o } 18func sh_catn(d: *u8, o: i64, v: i64) -> i64 { 19 let t: *u8=sys_mmap(28); var m: i64=v; var k: i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} 20 var q: i64=k-1; while q>=0{d[o]=t[q];o=o+1;q=q-1} return o 21} 22 23// request-line path (between the 1st and 2nd ASCII space). -> len into out (NUL-term). 24func sh_path(req: *u8, n: i64, out: *u8, cap: i64) -> i64 { 25 var s1: i64 = 0-1; var i: i64 = 0 26 while i < n { if (req[i] as i64)==32 { s1=i; i=n } else { i=i+1 } } 27 if s1 < 0 { out[0]=0 as u8; return 0 } 28 var p: i64 = s1+1; var o: i64 = 0 29 while p < n { let c: i64 = req[p] as i64; if c==32 { p=n } else { if o<cap-1 { out[o]=req[p]; o=o+1 } p=p+1 } } 30 out[o]=0 as u8; return o 31} 32// Host header value -> len into out (NUL-term). finds "\nHost:" (so it can't match the request line), skips 33// spaces, copies to CR/LF. case-insensitive on the header name. 34func sh_host(req: *u8, n: i64, out: *u8, cap: i64) -> i64 { 35 var i: i64 = 0; var hs: i64 = 0-1 36 while i + 6 <= n { 37 if (req[i] as i64)==10 { 38 let a: i64 = req[i+1] as i64; let b: i64 = req[i+2] as i64; let c: i64 = req[i+3] as i64; let d: i64 = req[i+4] as i64 39 var hm: i64 = 0 40 if a==72 { if b==111 { if c==115 { if d==116 { if (req[i+5] as i64)==58 { hm=1 } } } } } // "Host:" 41 if a==104 { if b==111 { if c==115 { if d==116 { if (req[i+5] as i64)==58 { hm=1 } } } } } // "host:" 42 if hm==1 { hs=i+6; i=n } 43 } 44 if hs<0 { i=i+1 } 45 } 46 if hs < 0 { out[0]=0 as u8; return 0 } 47 var p: i64 = hs 48 var sk: i64 = 1 49 while sk==1 { if p>=n { sk=0 } else { if (req[p] as i64)==32 { p=p+1 } else { sk=0 } } } 50 var o: i64 = 0 51 while p < n { let c: i64 = req[p] as i64; if c==13 { p=n } else { if c==10 { p=n } else { if o<cap-1 { out[o]=req[p]; o=o+1 } p=p+1 } } } 52 out[o]=0 as u8; return o 53} 54 55func sh_handle(req: *u8, n: i64, rt: *u8, rtn: i64, vt: *u8, vtn: i64, out: *u8, dec: *i64) -> i64 { 56 let hostbuf: *u8 = sys_mmap(256); let pathbuf: *u8 = sys_mmap(SH_MAGIC_4096) 57 let hl: i64 = sh_host(req, n, hostbuf, 256) 58 let pl: i64 = sh_path(req, n, pathbuf, SH_MAGIC_4096) 59 let pb: *i64 = sys_mmap(8) as *i64; let mb: *i64 = sys_mmap(8) as *i64 60 if rt_match(rt, rtn, hostbuf, hl, pathbuf, pl, pb, mb) == 1 { 61 dec[0]=SH_PROXY; dec[1]=pb[0]; dec[2]=mb[0]; return 0 62 } 63 let drbuf: *u8 = sys_mmap(SH_MAGIC_2048) 64 if sd_vhost(vt, vtn, hostbuf, hl, drbuf) == 1 { 65 let szb: *i64 = sys_mmap(16) as *i64; szb[0]=0 66 let body: *u8 = sys_read_file(drbuf, szb) 67 if (body as i64)!=0 { if szb[0]>0 { 68 dec[0]=SH_STATIC 69 var o: i64 = sh_cat(out, 0, "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\nConnection: close\r\nContent-Length: " as *u8) 70 o = sh_catn(out, o, szb[0]); o = sh_cat(out, o, "\r\n\r\n" as *u8); o = sh_catb(out, o, body, szb[0]) 71 return o 72 } } 73 } 74 dec[0]=SH_NOTFOUND 75 let b: *u8 = "<!doctype html><meta charset=utf-8><title>404</title><h1>404 &mdash; not found</h1>" as *u8 76 var bn: i64=0; while b[bn]!=(0 as u8){bn=bn+1} 77 var o: i64 = sh_cat(out, 0, "HTTP/1.1 404 Not Found\r\nContent-Type: text/html; charset=utf-8\r\nConnection: close\r\nContent-Length: " as *u8) 78 o = sh_catn(out, o, bn); o = sh_cat(out, o, "\r\n\r\n" as *u8); o = sh_catb(out, o, b, bn) 79 return o 80}