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}