nx_route_probe.nx source
↩ module page · 92 lines · 3347 B
1// nx_route_probe.nx -- latency-probed multi-path relay selection.
2//
3// Primitive 2 of NISHI_S_CLASS_ROUTING_ROADMAP: at call start, probe
4// every candidate relay's RTT live, combine with packet loss + a
5// jurisdiction penalty, and pick the lowest-cost path -- so a
6// Texas<->Belarus call prefers a Frankfurt relay over a US one even
7// when the US one is a hair faster (avoid US/adversary-jurisdiction
8// transit by policy). All Nishi: composes nx_udp_rv + sys_now_us;
9// the relays are our own nx_turn_relay (which answers STUN BINDING).
10//
11// cost(path) = rtt_ms + 30 * loss_pct + jurisdiction_penalty_ms
12//
13// The jurisdiction penalty is POLICY (operator-editable), not a magic
14// number baked in source -- the caller passes the avoid-jurisdiction
15// from ~/.nishi/jurisdiction config per
16// [[feedback-no-hardcoded-secrets-config-driven]].
17
18import "../runtime/nx_udp_rv.nx"
19
20const NX_ROUTE_JUR_PENALTY_MS: i64 = 50 // policy weight; caller may override
21
22// Pure: combined path cost. KAT-able.
23func nx_route_cost(rtt_ms: i64, loss_pct: i64, jur_penalty_ms: i64) -> i64 {
24 return rtt_ms + 30 * loss_pct + jur_penalty_ms
25}
26
27// Pure: index of the minimum cost, or -1 if n<=0. KAT-able.
28func nx_route_select(costs: *i64, n: i64) -> i64 {
29 if n <= 0 { return 0 - 1 }
30 var best: i64 = 0
31 var bc: i64 = costs[0]
32 var i: i64 = 1
33 while i < n {
34 if costs[i] < bc { bc = costs[i]; best = i }
35 i = i + 1
36 }
37 return best
38}
39
40// Pure: jurisdiction penalty. 50ms-equiv if the relay sits in the
41// jurisdiction the call wants to avoid, else 0.
42func nx_route_jur_penalty(relay_jur: i64, avoid_jur: i64) -> i64 {
43 if relay_jur == avoid_jur { return NX_ROUTE_JUR_PENALTY_MS }
44 return 0
45}
46
47func _rp_pfd_set_fd(buf: *u8, fd: i64) -> i64 {
48 buf[0]=fd&0xff; buf[1]=(fd>>8)&0xff; buf[2]=(fd>>16)&0xff; buf[3]=(fd>>24)&0xff
49 return 0
50}
51func _rp_pfd_set_events(buf: *u8, ev: i64) -> i64 {
52 buf[4]=ev&0xff; buf[5]=(ev>>8)&0xff
53 return 0
54}
55
56// Build a 20-byte STUN BINDING request (the relay answers 0x0101).
57func _rp_stun_binding(out: *u8, tx: *u8) -> i64 {
58 out[0]=0x00; out[1]=0x01
59 out[2]=0x00; out[3]=0x00
60 out[4]=0x21; out[5]=0x12; out[6]=0xa4; out[7]=0x42
61 var i: i64 = 0
62 while i < 12 { out[8+i] = tx[i]; i = i + 1 }
63 return 20
64}
65
66// Live: measure RTT (microseconds) to a relay via STUN BINDING.
67// Returns rtt_us (>=0) or -1 on timeout / send failure.
68func nx_route_probe_rtt(fd: i64, relay16: *u8, timeout_ms: i64) -> i64 {
69 let tx: *u8 = sys_mmap(16)
70 var i: i64 = 0
71 while i < 12 { tx[i] = (i * 13 + 1) & 0xff; i = i + 1 }
72 let req: *u8 = sys_mmap(32)
73 _rp_stun_binding(req, tx)
74 let t0: i64 = sys_now_us()
75 if nx_udpr_send(fd, req, 20, relay16) != 20 { return 0 - 1 }
76 let pf: *u8 = sys_mmap(8)
77 _rp_pfd_set_fd(pf, fd)
78 _rp_pfd_set_events(pf, 1)
79 let r: i64 = sys_poll(pf, 1, timeout_ms)
80 if r <= 0 { return 0 - 1 }
81 let rbuf: *u8 = sys_mmap(256)
82 let from: *u8 = sys_mmap(16)
83 let fl: *i64 = sys_mmap(16) as *i64
84 *fl = 16
85 let n: i64 = nx_udpr_recv(fd, rbuf, 256, from, fl)
86 if n < 20 { return 0 - 1 }
87 // Must be a STUN success (0x0101) with the magic cookie.
88 if rbuf[0] != 0x01 { return 0 - 1 }
89 if rbuf[1] != 0x01 { return 0 - 1 }
90 if rbuf[4] != 0x21 { return 0 - 1 }
91 return sys_now_us() - t0
92}