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}