code wiki / (root) / nx_quic_pkt.nx

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 }