code wiki / _hdl_build / _h2_multistream_curl_daemon.nx
_h2_multistream_curl_daemon.nx source
↩ module page · 278 lines · 13835 B
1// _h2_multistream_curl_daemon.nx -- TUTOR-BOOTSTRAP SCAFFOLD (Claude, authored
2// under the B1 rung(6) PERSISTENT-MULTI-STREAM external-curl interop step of the
3// R4-H2 HTTP/2-transport ladder), NOT credited as team self-authoring (back-fill
4// via the emitter-of-emitters once the daemon-from-spec organ exists).
5//
6// THE PERSISTENT MULTI-STREAM ALPN-h2 SERVE DAEMON: stands up OUR sovereign
7// ALPN-h2 TLS 1.3 server on 127.0.0.1:9444 and serves an EXTERNAL, INDEPENDENT h2
8// client (curl --http2 with libnghttp2/OpenSSL) that issues MULTIPLE same-origin
9// GETs. Unlike _h2_serve_curl_daemon.nx (which ACCEPTS HCD_N=3 SEPARATE
10// connections because its single-stream driver GOAWAYs after each request), this
11// daemon ACCEPTS EXACTLY ONE connection and serves up to MCD_MAX request streams
12// on it via the persistent driver h2_serve_connection_multi (runtime/
13// nx_h2_serve_multi.nx). An external curl given K same-origin URLs therefore
14// REUSES that ONE TCP connection (total num_connects across the K transfers = 1).
15//
16// MEASURED EXCEED + DISCRIMINATION (the gate):
17// POS (this daemon, persistent): curl url1 url2 ... urlK on 127.0.0.1:9444 ->
18// all K transfers HTTP/2 200, TOTAL num_connects = 1 (the connection is
19// REUSED across streams 1,3,5,...,2K-1).
20// NEG control (_h2_serve_curl_daemon, single-stream, port 9443): the SAME K
21// URLs -> each transfer opens a FRESH connection (total num_connects = K),
22// because the single-stream driver GOAWAYs + closes after each request.
23// The num_connects measurement DISCRIMINATES persistent multi-stream from
24// connection-per-request -- it is not a tautology.
25//
26// FLOW (main):
27// - mint a self-signed Ed25519 X.509 leaf (SAN=localhost) -- the SAME
28// sovereign cert path the proven daemon uses (mcd_make_cert).
29// - EXPORT that DER cert to a PEM file (/tmp/nx_h2_ms_cert.pem) so an external
30// curl can trust it via --cacert (composes nx_base64 b64_encode).
31// - socket / SO_REUSEADDR / bind 127.0.0.1:9444 / listen; print
32// "BOUND 127.0.0.1:9444" so the orchestrator's readiness gate fires.
33// - ONE accept -> fresh handshake entropy -> h2_serve_connection_multi
34// (MCD_MAX cap) -> close -> exit 0; the driver returns the COUNT of streams
35// served (>=1), else an honest negative -> stop-on-RED, no fake-green.
36//
37// HONEST verdict discipline: this organ's job is to BIND + SERVE >1 external h2
38// request STREAM on ONE connection. GREEN (server side) iff the handshake
39// completed and >=2 request streams were parsed + answered :status 200 on the SAME
40// connection. The EXTERNAL curl judgement ("using HTTP/2" + "Re-using existing
41// connection" + total num_connects=1 + K x "HTTP/2 200") is the interop phase,
42// judged from curl's OWN output, not from this organ's exit code.
43//
44// FOUNDED ON (composes, each imported EXACTLY ONCE; the persistent driver organ
45// re-exports the framing + 3 tls13 transport stones transitively):
46// - nx_h2_serve_multi.nx: h2_serve_connection_multi (the persistent driver).
47// - nx_x25519_ephemeral / nx_csprng / nx_ed25519_signature: keys + randomness.
48// - hub/nx_x509_build / nx_x509 / nx_x509_trust_store: self-signed leaf builder.
49// - nx_base64.nx: b64_encode for the PEM export (cert-trust interop path).
50// - nx_syscalls.nx: sockets + file I/O.
51//
52// license_tier: INDEPENDENT_REDERIVE
53// genealogy_id: international-research-sources/ietf/rfc_9113 (s5 multiplexing) + rfc_8446 + rfc_7301 + rfc_5280 + rfc_4648
54// lineage_id: nishi_h2_multistream_curl_daemon_b1r6
55
56import "nx_syscalls.nx"
57import "nx_h2_serve_multi.nx" // B1 rung(6): the PERSISTENT multi-stream driver
58 // (h2_serve_connection_multi) -- re-exports the
59 // framing + 3 tls13 transport stones transitively.
60import "nx_x25519_ephemeral.nx"
61import "nx_csprng.nx"
62import "nx_ed25519_signature.nx"
63import "hub/nx_x509_build.nx"
64import "nx_x509.nx"
65import "nx_x509_trust_store.nx"
66import "nx_base64.nx"
67
68// Max request streams this daemon will serve on the ONE accepted connection before
69// the driver winds down (honest backstop; the real stop is the client's close/
70// GOAWAY once it has fired all its URLs). 16 >> the gate's K so the client drives
71// the count, never this cap.
72const MCD_MAX: i64 = 16
73
74// 9444 (one above the single-stream daemon's 9443 so both can run for the
75// pos-vs-neg discrimination without a port clash).
76const MCD_PORT_REAL: i64 = 9444
77
78// ---- public-domain civil-date math (Howard Hinnant) -- inline (renamed mcd_) so
79// we do not import bin/nx_cert_gen.nx (which carries its own main()). ----
80func mcd_civil_from_days(days: i64, out_y: *i64, out_m: *i64, out_d: *i64) -> i64 {
81 let z: i64 = days + 719468
82 let era: i64 = if z >= 0 then z / 146097 else (z - 146096) / 146097
83 let doe: i64 = z - era * 146097
84 let yoe: i64 = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365
85 let y: i64 = yoe + era * 400
86 let doy: i64 = doe - (365 * yoe + yoe / 4 - yoe / 100)
87 let mp: i64 = (5 * doy + 2) / 153
88 let d: i64 = doy - (153 * mp + 2) / 5 + 1
89 var m: i64 = mp + 3
90 if mp < 10 { m = mp + 3 } else { m = mp - 9 }
91 var yy: i64 = y
92 if m <= 2 { yy = y + 1 }
93 out_y[0] = yy; out_m[0] = m; out_d[0] = d
94 return 0
95}
96func mcd_format_generalized_time(unix_sec: i64, out_15: *u8) -> i64 {
97 let days: i64 = unix_sec / 86400
98 let sod: i64 = unix_sec - days * 86400
99 let hh: i64 = sod / 3600
100 let mm: i64 = (sod - hh * 3600) / 60
101 let ss: i64 = sod - hh * 3600 - mm * 60
102 let yp: *i64 = sys_mmap(8) as *i64
103 let mp: *i64 = sys_mmap(8) as *i64
104 let dp: *i64 = sys_mmap(8) as *i64
105 mcd_civil_from_days(days, yp, mp, dp)
106 let y: i64 = yp[0]; let mo: i64 = mp[0]; let d: i64 = dp[0]
107 out_15[0] = ((0x30 + ((y / 1000) % 10)) & 0xff) as u8
108 out_15[1] = ((0x30 + ((y / 100) % 10)) & 0xff) as u8
109 out_15[2] = ((0x30 + ((y / 10) % 10)) & 0xff) as u8
110 out_15[3] = ((0x30 + ( y % 10)) & 0xff) as u8
111 out_15[4] = ((0x30 + (mo / 10)) & 0xff) as u8
112 out_15[5] = ((0x30 + (mo % 10)) & 0xff) as u8
113 out_15[6] = ((0x30 + (d / 10)) & 0xff) as u8
114 out_15[7] = ((0x30 + (d % 10)) & 0xff) as u8
115 out_15[8] = ((0x30 + (hh / 10)) & 0xff) as u8
116 out_15[9] = ((0x30 + (hh % 10)) & 0xff) as u8
117 out_15[10] = ((0x30 + (mm / 10)) & 0xff) as u8
118 out_15[11] = ((0x30 + (mm % 10)) & 0xff) as u8
119 out_15[12] = ((0x30 + (ss / 10)) & 0xff) as u8
120 out_15[13] = ((0x30 + (ss % 10)) & 0xff) as u8
121 out_15[14] = 0x5A as u8 // 'Z'
122 return 0
123}
124
125// Build the 16-byte sockaddr_in for 127.0.0.1:port.
126func mcd_addr(out: *u8, port: i64) -> i64 {
127 out[0] = 2 as u8; out[1] = 0 as u8 // AF_INET
128 out[2] = ((port >> 8) & 0xff) as u8 // port hi (network order)
129 out[3] = (port & 0xff) as u8 // port lo
130 out[4] = 127 as u8; out[5] = 0 as u8; out[6] = 0 as u8; out[7] = 1 as u8 // 127.0.0.1
131 var i: i64 = 8
132 while i < 16 { out[i] = 0 as u8; i = i + 1 }
133 return 0
134}
135
136// Generate the self-signed Ed25519 leaf (SAN=localhost).
137func mcd_make_cert(out_cert_der: *u8, out_cert_len: *i64, out_priv: *u8) -> i64 {
138 if nx_csprng_fill(out_priv, 32) != 0 { return 0 - 1 }
139 let pub32: *u8 = sys_mmap(32)
140 if ed25519_pub_from_priv(out_priv, pub32) != 0 { return 0 - 2 }
141 let now: i64 = sys_now_realtime_sec()
142 let nb: *u8 = sys_mmap(16)
143 let na: *u8 = sys_mmap(16)
144 mcd_format_generalized_time(now - 86400, nb)
145 mcd_format_generalized_time(now + 365 * 86400, na)
146 let san_name: *u8 = sys_mmap(16); nx_str_cpy(san_name, "localhost" as *u8)
147 let san_ptrs: *i64 = sys_mmap(8) as *i64; san_ptrs[0] = san_name as i64
148 let san_lens: *i64 = sys_mmap(8) as *i64; san_lens[0] = 9
149 let domain: *u8 = sys_mmap(16); nx_str_cpy(domain, "localhost" as *u8)
150 let inp: *NxX509BuildInputs = sys_mmap(256) as *NxX509BuildInputs
151 let in_rc: i64 = nx_x509_inputs_init(inp, domain, 9, san_ptrs, san_lens, 1,
152 out_priv, pub32, nb, na, now)
153 if in_rc != NX_X509_OK { return 0 - 3 }
154 let cdn: *i64 = sys_mmap(8) as *i64; cdn[0] = 0
155 let brc: i64 = nx_x509_build_self_signed(inp, out_cert_der, 8192, cdn)
156 if brc != NX_X509_OK { return 0 - 4 }
157 out_cert_len[0] = cdn[0]
158 return 0
159}
160
161// ---- PEM export (composes nx_base64 b64_encode, re-wrapped at 64 cols). ----
162func mcd_write_pem(cert_der: *u8, der_len: i64, path_z: *u8) -> i64 {
163 let b64cap: i64 = 4 * ((der_len + 2) / 3) + 8
164 let b64buf: *u8 = sys_mmap(b64cap)
165 let b64n: i64 = b64_encode(cert_der, der_len, b64buf)
166 if b64n <= 0 { return 0 - 1 }
167 let fd: i64 = sys_openat_wr(path_z, 0x1a4)
168 if fd < 0 { return 0 - 2 }
169 if sys_write(fd, "-----BEGIN CERTIFICATE-----\n" as *u8, 28) != 28 { sys_close(fd); return 0 - 3 }
170 var off: i64 = 0
171 while off < b64n {
172 var line: i64 = 64
173 if b64n - off < 64 { line = b64n - off }
174 let w: i64 = sys_write(fd, ((b64buf as i64) + off) as *u8, line)
175 if w != line { sys_close(fd); return 0 - 4 }
176 if sys_write(fd, "\n" as *u8, 1) != 1 { sys_close(fd); return 0 - 5 }
177 off = off + line
178 }
179 if sys_write(fd, "-----END CERTIFICATE-----\n" as *u8, 26) != 26 { sys_close(fd); return 0 - 6 }
180 sys_close(fd)
181 return 0
182}
183
184// ---- verdict log: knowledge/status/h2_multistream.log ----
185// served_count >= 2 on ONE connection -> GREEN(server-side); else RED+code. ----
186func mcd_log(verdict_green: i64, served_or_code: i64) -> i64 {
187 let lfd: i64 = sys_openat_append("knowledge/status/h2_multistream.log" as *u8, 0x1a4)
188 if lfd < 0 { return 0 }
189 sys_write(lfd, "B1-R6-H2-MULTISTREAM organ=_h2_multistream_curl_daemon " as *u8, 55)
190 if verdict_green == 1 {
191 sys_write(lfd, "alpn=h2 one-conn streams-served=" as *u8, 32)
192 } else {
193 sys_write(lfd, "verdict=RED code=" as *u8, 17)
194 }
195 var v: i64 = served_or_code; if v < 0 { sys_write(lfd, "-" as *u8, 1); v = 0 - v }
196 let t: *u8 = sys_mmap(28); var kk: i64 = 0
197 if v == 0 { t[0] = 48 as u8; kk = 1 }
198 while v > 0 { t[kk] = (48 + (v % 10)) as u8; v = v / 10; kk = kk + 1 }
199 while kk > 0 { kk = kk - 1; sys_write(lfd, (((t as i64)+kk) as *u8), 1) }
200 if verdict_green == 1 {
201 sys_write(lfd, " verdict=GREEN(server-side: >1 stream on 1 conn)\n" as *u8, 49)
202 } else {
203 sys_write(lfd, "\n" as *u8, 1)
204 }
205 sys_close(lfd)
206 return 0
207}
208
209func main() -> i64 {
210 sys_write(1, "_h2_multistream_curl_daemon: OUR sovereign persistent ALPN-h2 server (1 conn, many streams) for EXTERNAL curl\n" as *u8, 109)
211
212 // ---- body the server serves to every stream ----
213 let body: *u8 = sys_mmap(64)
214 let bsrc: *u8 = "hello from nishi h2 server (persistent multi-stream)" as *u8
215 var blen: i64 = 0
216 while bsrc[blen] != (0 as u8) { body[blen] = bsrc[blen]; blen = blen + 1 }
217
218 // ---- mint cert + export PEM ----
219 let cert_der: *u8 = sys_mmap(8192)
220 let cert_len: *i64 = sys_mmap(8) as *i64
221 let ed_priv: *u8 = sys_mmap(32)
222 if mcd_make_cert(cert_der, cert_len, ed_priv) < 0 {
223 sys_write(1, " FAIL cert build\n" as *u8, 18); mcd_log(0, 0 - 90); sys_exit(90); return 90
224 }
225 sys_write(1, " cert minted (SAN=localhost, Ed25519 self-signed)\n" as *u8, 51)
226 let pem_path: *u8 = sys_mmap(64)
227 nx_str_cpy(pem_path, "/tmp/nx_h2_ms_cert.pem" as *u8)
228 if mcd_write_pem(cert_der, cert_len[0], pem_path) < 0 {
229 sys_write(1, " FAIL pem write\n" as *u8, 17); mcd_log(0, 0 - 91); sys_exit(91); return 91
230 }
231 sys_write(1, " cert.pem written /tmp/nx_h2_ms_cert.pem\n" as *u8, 42)
232
233 let srand: *u8 = sys_mmap(32)
234 let sxpriv: *u8 = sys_mmap(32)
235
236 // ---- socket / SO_REUSEADDR / bind 127.0.0.1:9444 / listen ----
237 let addr: *u8 = sys_mmap(16)
238 mcd_addr(addr, MCD_PORT_REAL)
239 let lfd: i64 = sys_socket(AF_INET, SOCK_STREAM, 0)
240 if lfd < 0 { mcd_log(0, 0 - 94); sys_exit(94); return 94 }
241 let optval: *u8 = sys_mmap(4)
242 optval[0] = 1 as u8; optval[1] = 0 as u8; optval[2] = 0 as u8; optval[3] = 0 as u8
243 sys_setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, optval, 4)
244 if sys_bind(lfd, addr, 16) < 0 { mcd_log(0, 0 - 95); sys_exit(95); return 95 }
245 if sys_listen(lfd, 4) < 0 { mcd_log(0, 0 - 96); sys_exit(96); return 96 }
246 sys_write(1, "BOUND 127.0.0.1:9444\n" as *u8, 21)
247
248 // ---- ONE accept -> serve MANY streams on it ----
249 let scfd: i64 = sys_accept(lfd)
250 if scfd < 0 { mcd_log(0, 0 - 97); sys_close(lfd); sys_exit(97); return 97 }
251 if nx_csprng_fill(srand, 32) != 0 {
252 sys_close(scfd); mcd_log(0, 0 - 92); sys_close(lfd); sys_exit(92); return 92
253 }
254 if x25519_keypair_private(sxpriv) != 0 {
255 sys_close(scfd); mcd_log(0, 0 - 93); sys_close(lfd); sys_exit(93); return 93
256 }
257 let sr: i64 = h2_serve_connection_multi(scfd, srand, sxpriv, cert_der, cert_len[0], ed_priv, body, blen, MCD_MAX)
258 sys_close(scfd)
259 sys_close(lfd)
260
261 if sr < 2 {
262 // <2 streams served = persistence NOT demonstrated -> honest RED, no fake-green.
263 sys_write(1, " FAIL persistent multi-stream not demonstrated (served<2)\n" as *u8, 58)
264 mcd_log(0, sr)
265 var ec: i64 = sr; if ec < 0 { ec = 0 - sr }
266 if ec == 0 { ec = 1 }
267 sys_exit(ec); return ec
268 }
269
270 sys_write(1, "SERVED MULTI: streams=" as *u8, 22)
271 let t2: *u8 = sys_mmap(8); var v2: i64 = sr; var n2: i64 = 0
272 if v2 == 0 { t2[0] = 48 as u8; n2 = 1 }
273 while v2 > 0 { t2[n2] = (48 + (v2 % 10)) as u8; v2 = v2 / 10; n2 = n2 + 1 }
274 while n2 > 0 { n2 = n2 - 1; sys_write(1, (((t2 as i64)+n2) as *u8), 1) }
275 sys_write(1, " on ONE connection, :status 200 each, exiting 0\n" as *u8, 48)
276 mcd_log(1, sr)
277 sys_exit(0); return 0
278}