moqtap_client/draft16/session/
request_id.rs1use moqtap_codec::varint::VarInt;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum Role {
6 Client,
8 Server,
10}
11
12#[derive(Debug, thiserror::Error, PartialEq, Eq)]
14pub enum RequestIdError {
15 #[error("request ID {0} exceeds max {1}")]
17 ExceedsMax(u64, u64),
18 #[error("request ID {0} has wrong parity for {1:?}")]
20 WrongParity(u64, Role),
21 #[error("max request ID can only increase: was {0}, got {1}")]
23 Decreased(u64, u64),
24 #[error("no request IDs available (blocked)")]
26 Blocked,
27}
28
29pub struct RequestIdAllocator {
36 role: Role,
37 next_id: u64,
38 max_id: u64,
39}
40
41impl RequestIdAllocator {
42 pub fn new(role: Role) -> Self {
44 let next_id = match role {
45 Role::Client => 0,
46 Role::Server => 1,
47 };
48 Self { role, next_id, max_id: 0 }
49 }
50
51 pub fn allocate(&mut self) -> Result<VarInt, RequestIdError> {
53 if self.max_id == 0 || self.next_id > self.max_id {
54 return Err(RequestIdError::Blocked);
55 }
56 let id = VarInt::from_u64(self.next_id).unwrap();
57 self.next_id += 2;
58 Ok(id)
59 }
60
61 pub fn update_max(&mut self, new_max: u64) -> Result<(), RequestIdError> {
63 if new_max <= self.max_id {
64 return Err(RequestIdError::Decreased(self.max_id, new_max));
65 }
66 self.max_id = new_max;
67 Ok(())
68 }
69
70 pub fn validate_peer_id(&self, id: u64) -> Result<(), RequestIdError> {
72 let expected_even = match self.role {
74 Role::Client => false, Role::Server => true, };
77 let is_even = id % 2 == 0;
78 if is_even != expected_even {
79 let peer_role = match self.role {
80 Role::Client => Role::Server,
81 Role::Server => Role::Client,
82 };
83 return Err(RequestIdError::WrongParity(id, peer_role));
84 }
85 if id > self.max_id {
86 return Err(RequestIdError::ExceedsMax(id, self.max_id));
87 }
88 Ok(())
89 }
90
91 pub fn is_blocked(&self) -> bool {
93 self.max_id == 0 || self.next_id > self.max_id
94 }
95
96 pub fn max_id(&self) -> u64 {
98 self.max_id
99 }
100}