nx_quic_pkt.nx source
↩ module page · 45 lines · 2039 B
1// nx_quic_pkt.nx -- RUNG 2 of the sovereign QUIC transport: packet number encode/decode
2// (RFC 9000 sec 17.1 + Appendix A.2 sample-encode / A.3 sample-decode). Packet numbers are sent
3// truncated (1-4 bytes) and reconstructed from the largest received PN; getting this exactly right
4// (incl. the wraparound windows) is mandatory for AEAD nonce derivation in R5. No float.
5// license_tier: ORIGINAL
6import "nx_quic_wire.nx"
7const K_MAGIC_4611686018427387904: i64 = 4611686018427387904
8
9// RFC 9000 A.3 DecodePacketNumber(largest_pn, truncated_pn, pn_nbits) -> full packet number
10func quic_pn_decode(largest_pn: i64, truncated_pn: i64, pn_nbits: i64) -> i64 {
11 let expected_pn: i64 = largest_pn + 1
12 let pn_win: i64 = 1 << pn_nbits
13 let pn_hwin: i64 = pn_win / 2
14 let pn_mask: i64 = pn_win - 1
15 // candidate_pn = (expected_pn & ~pn_mask) | truncated_pn (clear low bits, splice in truncated)
16 let candidate_pn: i64 = (expected_pn - (expected_pn & pn_mask)) | truncated_pn
17 if candidate_pn + pn_hwin <= expected_pn {
18 if candidate_pn + pn_win < K_MAGIC_4611686018427387904 { return candidate_pn + pn_win }
19 }
20 if candidate_pn > expected_pn + pn_hwin {
21 if candidate_pn >= pn_win { return candidate_pn - pn_win }
22 }
23 return candidate_pn
24}
25
26// RFC 9000 A.2: minimum bytes (1..4) to encode full_pn so it decodes unambiguously vs largest_acked
27// (largest_acked < 0 means none acked yet). Need 2^(8*nbytes) > 2*(full_pn - largest_acked).
28func quic_pn_enc_len(full_pn: i64, largest_acked: i64) -> i64 {
29 var num_unacked: i64 = full_pn + 1
30 if largest_acked >= 0 { num_unacked = full_pn - largest_acked }
31 let need: i64 = 2 * num_unacked
32 var nb: i64 = 1
33 while nb < 4 {
34 if (1 << (8 * nb)) > need { return nb }
35 nb = nb + 1
36 }
37 return 4
38}
39
40// the truncated PN actually placed on the wire = low (8*nbytes) bits of full_pn
41func quic_pn_truncate(full_pn: i64, nbytes: i64) -> i64 {
42 return full_pn & ((1 << (8 * nbytes)) - 1)
43}
44
45func main() -> i64 { return 0 }