code wiki / (root) / nx_edge_serve_static.nx

nx_edge_serve_static.nx source

↩ module page · 112 lines · 3784 B

1// nx_edge_serve_static.nx -- substrate primitive that turns a 2// CONNECTED Tls13ServerSession into a one-shot HTTPS serving call. 3// 4// What this ships: 5// nx_edge_build_http_response(content, content_len, out, out_cap) 6// Builds a minimal HTTP/1.1 200 OK response with Content-Length 7// header and the given body. Returns total bytes written. 8// 9// nx_edge_serve_static_response(session, content, content_len, out, out_cap) 10// After handshake completes (state CONNECTED), this builds an 11// HTTP/1.1 response wrapping `content` and AEAD-encrypts it as 12// a TLS application_data record under server_app_traffic_key + iv. 13// Returns total bytes written to `out` (the wire bytes to send 14// to the client over the TCP socket). 15// 16// This is the final substrate brick between the substrate's TLS 1.3 17// server arc (10 stones + app_send/recv shipped) and an operator- 18// runnable HTTPS daemon. Operator integration steps documented in 19// docs/NISHIFAMILY_DEPLOY_RUNBOOK_2026_05_20.md. 20// 21// license_tier: ORIGINAL 22 23import "nx_syscalls.nx" 24import "nx_tls13_server_session.nx" 25import "nx_tls13_server_session_app_data.nx" 26 27// Append a C-string to a byte buffer; returns new write position. 28func edge_put_cstr(out: *u8, pos: i64, s: *u8) -> i64 { 29 var i: i64 = 0 30 var p: i64 = pos 31 while s[i] != 0 { 32 out[p] = s[i] 33 p = p + 1 34 i = i + 1 35 } 36 return p 37} 38 39// Write a positive integer as decimal ASCII; returns new write position. 40func edge_put_int(out: *u8, pos: i64, value: i64) -> i64 { 41 var p: i64 = pos 42 if value == 0 { 43 out[p] = 0x30 as u8 44 return p + 1 45 } 46 let scratch: *u8 = sys_mmap(24) 47 var n: i64 = 0 48 var v: i64 = value 49 while v > 0 { 50 scratch[n] = ((0x30 + (v % 10)) & 0xff) as u8 51 v = v / 10 52 n = n + 1 53 } 54 var j: i64 = n - 1 55 while j >= 0 { 56 out[p] = scratch[j] 57 p = p + 1 58 j = j - 1 59 } 60 return p 61} 62 63// Build a minimal HTTP/1.1 200 OK response wrapping content. 64// Returns total bytes written. 65func nx_edge_build_http_response( 66 content: *u8, content_len: i64, 67 out: *u8, out_cap: i64 68) -> i64 { 69 if (content as i64) == 0 { return -1 } 70 if content_len < 0 { return -1 } 71 // Pre-size: status line ~17 + headers ~80 + body 72 if out_cap < 100 + content_len { return -1 } 73 74 var p: i64 = 0 75 p = edge_put_cstr(out, p, "HTTP/1.1 200 OK\r\n") 76 p = edge_put_cstr(out, p, "Content-Type: text/html; charset=utf-8\r\n") 77 p = edge_put_cstr(out, p, "Content-Length: ") 78 p = edge_put_int(out, p, content_len) 79 p = edge_put_cstr(out, p, "\r\nConnection: close\r\n\r\n") 80 81 var ci: i64 = 0 82 while ci < content_len { 83 out[p + ci] = content[ci] 84 ci = ci + 1 85 } 86 return p + content_len 87} 88 89// Serve a static HTML/text response: build HTTP/1.1 200 OK + encrypt 90// as a TLS application_data record. Caller supplies the CONNECTED 91// session. Returns wire-byte count or negative verdict. 92func nx_edge_serve_static_response( 93 session: *Tls13ServerSession, 94 content: *u8, content_len: i64, 95 out: *u8, out_cap: i64 96) -> i64 { 97 if (session as i64) == 0 { return 0 - NX_TLS13_SSESSION_BAD_STATE } 98 if session.state != NX_TLS13_SSTATE_CONNECTED { 99 return 0 - NX_TLS13_SSESSION_BAD_STATE 100 } 101 102 // 1. Build the plaintext HTTP/1.1 response 103 let http_cap: i64 = 256 + content_len 104 let http_buf: *u8 = sys_mmap(http_cap) 105 let http_len: i64 = nx_edge_build_http_response( 106 content, content_len, http_buf, http_cap) 107 if http_len < 0 { return 0 - NX_TLS13_SSESSION_INTERNAL } 108 109 // 2. Encrypt the HTTP response as a TLS application_data record 110 return nx_tls13_server_session_app_send( 111 session, http_buf, http_len, out, out_cap) 112}