code wiki / _hdl_build / nx_kaprobe.nx

nx_kaprobe.nx source

↩ module page · 203 lines · 9402 B

1// nx_kaprobe.nx -- HTTP/1.1 KEEP-ALIVE CONNECTION REUSE probe + capability proof (census gap #3: 2// "connection reuse ABSENT: Connection: close ... SOTA keep-alive = 50-80% latency cut for multi-page hosts"). 3// The proven TLS send/recv core (nx_https_req_complete) ALREADY leaves the session CONNECTED after a 4// Content-Length response (cl-stop) with the app-data seq counters advanced -- so a SECOND request over the 5// SAME session/fd just works. The only thing forcing teardown was the request builder's "Connection: close". 6// This organ builds a "Connection: keep-alive" request and measures TWO batches of K GETs to the sovereign 7// edge (loopback 127.0.0.1:8443), both with a WARM cert cache (fair vs the current cache-only production): 8// BATCH A (reuse): 1 handshake + K GETs over ONE session. 9// BATCH B (no-reuse): K (handshake + GET + close) cycles = today's close-per-request behavior. 10// saving = B - A = ~(K-1) handshakes avoided. Emits netobs_keepalive_batch_ms / _noreuse_batch_ms / 11// _saved_ms / _per_req_ms so /netobs tracks the reuse win as a continuous series. Self-diagnosing: if the 12// server does not honor keep-alive (request 2 fails on a torn session) the probe reports VERDICT=RED honestly. 13// Rule 26: read-only network probe, zero hardware writes. Envelope: K=5 GETs/batch, loopback-only, 8s tmo. 14// license_tier: ORIGINAL expect_exit: 0 15import "nx_sovjson_lib.nx" 16import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc) 17import "nx_connect.nx" // bounded connect: a raw sys_connect hangs ~127s on a black-holed host 18import "nx_syscalls.nx" 19import "nx_csprng.nx" 20import "nx_x509_trust_store.nx" 21import "nx_trust_store_load_from_certdata.nx" 22import "nx_tls13_client_validate_certificate.nx" 23import "nx_tls13_client_session_run.nx" 24import "nx_tls13_client_session.nx" 25import "nx_https_get_complete.nx" 26import "nx_tls_cert_cache.nx" 27const KA_MAGIC_8443: i64 = 8443 28const KA_MAGIC_4194304: i64 = 4194304 29const KA_MAGIC_1024: i64 = 1024 30const KA_MAGIC_4096: i64 = 4096 31 32const KA_CERTDATA: *u8 = "data/mozilla_certdata.txt" as *u8 33const KA_CERT_CAP: i64 = 16384 34const KA_OUTCAP: i64 = 262144 35const KA_LEDGER: *u8 = "knowledge/status/netobs_metrics.log" 36const KA_K: i64 = 5 37 38func ka_w(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 39// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer 40// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the 41// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls). 42// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign. 43func ka_wn(v: i64) -> i64 { nxi_out(v); return 0 } 44func ka_cat(d: *u8, o: i64, s: *u8) -> i64 { return sj_cat(d, o, s) } 45func ka_catn(d: *u8, o: i64, v: i64) -> i64 { return sj_catn(d, o, v) } 46func ka_mrow(lb: *u8, o: i64, name: *u8, ts: i64, val: i64) -> i64 { 47 var p: i64 = ka_cat(lb, o, "METRIC " as *u8) 48 p = ka_cat(lb, p, name) 49 p = ka_cat(lb, p, " t_us=" as *u8) 50 p = ka_catn(lb, p, sys_now_us()) 51 p = ka_cat(lb, p, " ts=" as *u8) 52 p = ka_catn(lb, p, ts) 53 p = ka_cat(lb, p, " value=" as *u8) 54 p = ka_catn(lb, p, val) 55 p = ka_cat(lb, p, " unit=ms src=nx_kaprobe\n" as *u8) 56 return p 57} 58func ka_append(buf: *u8, n: i64) -> i64 { 59 var fd: i64 = sys_openat_append(KA_LEDGER, 420) 60 if fd < 0 { let cf: i64 = sys_openat_wr(KA_LEDGER, 420); if cf >= 0 { sys_close(cf) } fd = sys_openat_append(KA_LEDGER, 420) } 61 if fd < 0 { return 0 } 62 var w: i64 = 0 63 while w < n { let src: *u8 = ((buf as i64) + w) as *u8; let r: i64 = sys_write(fd, src, n - w); if r <= 0 { w = n } else { w = w + r } } 64 sys_close(fd) 65 return 0 66} 67// keep-alive HTTP/1.1 GET request bytes into out. minimal headers (our own edge; no UA needed). returns len. 68func ka_build_request(out: *u8, path: *u8, host: *u8) -> i64 { 69 var o: i64 = ka_cat(out, 0, "GET " as *u8) 70 o = ka_cat(out, o, path) 71 o = ka_cat(out, o, " HTTP/1.1\r\nHost: " as *u8) 72 o = ka_cat(out, o, host) 73 o = ka_cat(out, o, "\r\nConnection: keep-alive\r\n\r\n" as *u8) 74 return o 75} 76// connect a fresh socket to 127.0.0.1:8443 (the sovereign edge). returns fd or -1. 77func ka_connect() -> i64 { 78 let fd: i64 = sys_socket(2, 1, 0) 79 if fd < 0 { return 0 - 1 } 80 sys_set_socket_timeout(fd, 8) 81 let sa: *u8 = sys_mmap(16) 82 sa[0] = 2 as u8 83 sa[1] = 0 as u8 84 sa[2] = ((KA_MAGIC_8443 >> 8) & 0xff) as u8 85 sa[3] = (KA_MAGIC_8443 & 0xff) as u8 86 sa[4] = 127 as u8 87 sa[5] = 0 as u8 88 sa[6] = 0 as u8 89 sa[7] = 1 as u8 90 var zi: i64 = 8 91 while zi < 16 { sa[zi] = 0 as u8; zi = zi + 1 } 92 if nx_connect_bounded(fd, sa, 16, NX_CONN_DEFAULT_MS) < 0 { sys_close(fd); return 0 - 1 } 93 return fd 94} 95// one warm TLS 1.3 handshake on an already-connected fd. returns session i64 (>0) or <=0 on fail. 96func ka_handshake(store: *TrustStore, host: *u8, hlen: i64, now: i64, fd: i64) -> i64 { 97 let vc: *TlsValidationContext = sys_mmap(128) as *TlsValidationContext 98 tcc_load(host, hlen, now, vc) 99 tcc_arm(vc) 100 vc.store = store 101 vc.sni_host = host 102 vc.sni_host_len = hlen 103 vc.now_epoch = now 104 let cr: *u8 = sys_mmap(32) 105 nx_csprng_fill(cr, 32) 106 let priv: *u8 = sys_mmap(32) 107 nx_csprng_fill(priv, 32) 108 let sr: i64 = nx_tls13_client_session_run(fd, host, hlen, cr, priv, vc) 109 tcc_save(host, hlen, now, vc) 110 return sr 111} 112 113func main(argc: i64, argv: *i64) -> i64 { 114 let now: i64 = sys_now_realtime_sec() 115 let r: i64 = nx_trust_store_load_from_certdata(KA_CERTDATA, 512, KA_MAGIC_4194304) 116 if r <= 0 { ka_w("NX-KAPROBE FAIL trust-store load\n" as *u8); sys_exit(1); return 1 } 117 let store: *TrustStore = r as *TrustStore 118 let host: *u8 = "nishifamily.com\x00" as *u8 119 let hlen: i64 = 15 120 let path: *u8 = "/netobs\x00" as *u8 121 let out: *u8 = sys_mmap(KA_OUTCAP) 122 let req: *u8 = sys_mmap(KA_MAGIC_1024) 123 let req_len: i64 = ka_build_request(req, path, host) 124 125 // ---- WARMUP: one handshake+GET so the cert cache is warm for BOTH batches (fair comparison) ---- 126 let wfd: i64 = ka_connect() 127 if wfd < 0 { ka_w("NX-KAPROBE FAIL warmup connect (edge 127.0.0.1:8443 down?)\n" as *u8); sys_exit(2); return 2 } 128 let wsr: i64 = ka_handshake(store, host, hlen, now, wfd) 129 if wsr <= 0 { sys_close(wfd); ka_w("NX-KAPROBE FAIL warmup handshake\n" as *u8); sys_exit(2); return 2 } 130 let wsession: *Tls13ClientSession = wsr as *Tls13ClientSession 131 nx_https_req_complete(wsession, wfd, req, req_len, out, KA_OUTCAP) 132 sys_close(wfd) 133 134 // ---- BATCH A: 1 handshake + K GETs over ONE session (keep-alive reuse) ---- 135 let afd: i64 = ka_connect() 136 if afd < 0 { ka_w("NX-KAPROBE FAIL batchA connect\n" as *u8); sys_exit(2); return 2 } 137 let a0: i64 = sys_now_ms() 138 let asr: i64 = ka_handshake(store, host, hlen, now, afd) 139 if asr <= 0 { sys_close(afd); ka_w("NX-KAPROBE FAIL batchA handshake\n" as *u8); sys_exit(2); return 2 } 140 let asession: *Tls13ClientSession = asr as *Tls13ClientSession 141 var aok: i64 = 1 142 var ak: i64 = 0 143 while ak < KA_K { 144 let an: i64 = nx_https_req_complete(asession, afd, req, req_len, out, KA_OUTCAP) 145 if an <= 0 { aok = 0; ak = KA_K } else { ak = ak + 1 } 146 } 147 let a1: i64 = sys_now_ms() 148 sys_close(afd) 149 let batchA: i64 = a1 - a0 150 151 // ---- BATCH B: K (handshake + GET + close) cycles = current close-per-request behavior ---- 152 let b0: i64 = sys_now_ms() 153 var bok: i64 = 1 154 var bk: i64 = 0 155 while bk < KA_K { 156 let bfd: i64 = ka_connect() 157 if bfd < 0 { bok = 0; bk = KA_K } else { 158 let bsr: i64 = ka_handshake(store, host, hlen, now, bfd) 159 if bsr <= 0 { sys_close(bfd); bok = 0; bk = KA_K } else { 160 let bsession: *Tls13ClientSession = bsr as *Tls13ClientSession 161 let bn: i64 = nx_https_req_complete(bsession, bfd, req, req_len, out, KA_OUTCAP) 162 sys_close(bfd) 163 if bn <= 0 { bok = 0; bk = KA_K } else { bk = bk + 1 } 164 } 165 } 166 } 167 let b1: i64 = sys_now_ms() 168 let batchB: i64 = b1 - b0 169 170 // ---- verdict + emit ---- 171 var verdict_green: i64 = 0 172 if aok == 1 { if bok == 1 { if batchA <= batchB { verdict_green = 1 } } } 173 var saved: i64 = batchB - batchA 174 if saved < 0 { saved = 0 } 175 var perreq: i64 = batchA / KA_K 176 177 let lb: *u8 = sys_mmap(KA_MAGIC_4096) 178 var o: i64 = 0 179 if aok == 1 { o = ka_mrow(lb, o, "netobs_keepalive_batch_ms" as *u8, now, batchA); o = ka_mrow(lb, o, "netobs_keepalive_per_req_ms" as *u8, now, perreq) } 180 if bok == 1 { o = ka_mrow(lb, o, "netobs_noreuse_batch_ms" as *u8, now, batchB) } 181 if verdict_green == 1 { o = ka_mrow(lb, o, "netobs_keepalive_saved_ms" as *u8, now, saved) } 182 if o > 0 { ka_append(lb, o) } 183 184 ka_w("NX-KAPROBE K=" as *u8) 185 ka_wn(KA_K) 186 ka_w(" reuse(1hs+KGET)=" as *u8) 187 ka_wn(batchA) 188 ka_w("ms noreuse(KhsKGET)=" as *u8) 189 ka_wn(batchB) 190 ka_w("ms saved=" as *u8) 191 ka_wn(saved) 192 ka_w("ms per_req=" as *u8) 193 ka_wn(perreq) 194 ka_w("ms aok=" as *u8) 195 ka_wn(aok) 196 ka_w(" bok=" as *u8) 197 ka_wn(bok) 198 ka_w(" envelope=K5,loopback-8443,warm-cache,tmo-8s VERDICT=" as *u8) 199 if verdict_green == 1 { ka_w("GREEN\n" as *u8); sys_exit(0); return 0 } 200 ka_w("RED\n" as *u8) 201 sys_exit(1) 202 return 1 203}