code wiki / (root) / nx_audit_server_daemon.nx

nx_audit_server_daemon.nx source

↩ module page · 95 lines · 3842 B

1// nx_audit_server_daemon.nx -- accept-loop variant of audit server. 2// 3// Sibling of nx_audit_server_main.nx (accept-once, used by the 4// loopback bench). This file is the LONG-RUNNING daemon: binds 5// 127.0.0.1:51847, accepts forever, serves docs/audit/{index.html, 6// snapshot.json} via nx_pages_static. 7// 8// Per cardinal user-owns-every-bit: this binary does NOT install 9// itself as a service. Caller installs via: 10// - bench/nx_audit_serve.sh (bash supervisor wrapper) 11// - or by hand: `./nx_audit_server_daemon &` 12// 13// Per cardinal feedback-bounded-loop-discipline-jpl-rule-2: the 14// accept loop is bounded by an inner request budget (1M requests 15// before clean exit to let the parent supervisor recycle). This 16// is the Erlang let-it-crash discipline applied -- a long-lived 17// process gives the parent supervisor an opportunity to refresh 18// state periodically. 19// 20// expect_exit: 0 (never, in normal operation; bench runs with 21// a kill-after-N-seconds harness) 22 23import "nx_syscalls_x86_64.nx" 24import "nx_http_server.nx" 25import "nx_pages_static.nx" 26 27const NXAD_PORT: i64 = 51847 28const NXAD_REQ_CAP: i64 = 8192 29const NXAD_RESP_CAP: i64 = 524288 // 512 KB 30const NXAD_REQUEST_BUDGET: i64 = 1000000 // recycle after 1M reqs 31 32func main() -> i64 { 33 // Build sockaddr_in for 127.0.0.1:51847. 34 let addr: *u8 = sys_mmap(16) 35 let a_rc: i64 = nx_http_server_addr_loopback(addr, NXAD_PORT) 36 if a_rc != 16 { return 10 } 37 38 // Bind + listen. 39 let lv: *i64 = sys_mmap(8) as *i64 40 let lfd: i64 = nx_http_server_listen(addr, 64, lv) 41 if lfd < 0 { return 20 + lv[0] } 42 43 let base: *u8 = "docs" as *u8 44 let base_n: i64 = 4 45 46 // Bounded accept loop (JPL Rule 2 discipline). 47 var n_served: i64 = 0 48 while n_served < NXAD_REQUEST_BUDGET { 49 let av: *i64 = sys_mmap(8) as *i64 50 let cfd: i64 = nx_http_server_accept_one(lfd, av) 51 if cfd < 0 { 52 // accept() failed -- treat as transient (EINTR etc.) 53 // and continue; supervisor will catch repeated failures 54 // via the outer respawn logic. 55 n_served = n_served + 1 56 // bounded iteration cap as belt-and-braces 57 if n_served >= NXAD_REQUEST_BUDGET { return 0 } 58 } 59 60 if cfd >= 0 { 61 // Per-request scratch. Allocated outside the loop body 62 // would persist; allocating here per-iter is bounded by 63 // request budget. Future: nx_arena_scope for amortization. 64 let req_buf: *u8 = sys_mmap(NXAD_REQ_CAP) 65 let om: *i64 = sys_mmap(8) as *i64 66 let opo: *i64 = sys_mmap(8) as *i64 67 let opl: *i64 = sys_mmap(8) as *i64 68 let ocl: *i64 = sys_mmap(8) as *i64 69 let obo: *i64 = sys_mmap(8) as *i64 70 let orn: *i64 = sys_mmap(8) as *i64 71 72 let rrc: i64 = nx_http_server_read_request(cfd, req_buf, NXAD_REQ_CAP, 73 om, opo, opl, ocl, obo, orn) 74 if rrc == NXS_OK { 75 let path_ptr: *u8 = ((req_buf as i64) + opo[0]) as *u8 76 let path_n: i64 = opl[0] 77 let resp_buf: *u8 = sys_mmap(NXAD_RESP_CAP) 78 let resp_n: *i64 = sys_mmap(8) as *i64 79 nx_pages_serve_file(path_ptr, path_n, 80 base, base_n, 81 om[0], 82 resp_buf, NXAD_RESP_CAP, resp_n) 83 nx_http_server_send_response(cfd, resp_buf, resp_n[0]) 84 } else { 85 // Bad request -- close connection. 86 sys_close(cfd) 87 } 88 n_served = n_served + 1 89 } 90 } 91 92 // Clean exit after request budget; parent supervisor will respawn. 93 sys_close(lfd) 94 return 0 95}