moqtap_client/draft17/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: u64::MAX }
50 }
51
52 pub fn allocate(&mut self) -> Result<VarInt, RequestIdError> {
54 if self.max_id == 0 || self.next_id > self.max_id {
55 return Err(RequestIdError::Blocked);
56 }
57 let id = VarInt::from_u64(self.next_id).unwrap();
58 self.next_id += 2;
59 Ok(id)
60 }
61
62 pub fn update_max(&mut self, new_max: u64) -> Result<(), RequestIdError> {
64 if new_max <= self.max_id {
65 return Err(RequestIdError::Decreased(self.max_id, new_max));
66 }
67 self.max_id = new_max;
68 Ok(())
69 }
70
71 pub fn validate_peer_id(&self, id: u64) -> Result<(), RequestIdError> {
73 let expected_even = match self.role {
75 Role::Client => false, Role::Server => true, };
78 let is_even = id % 2 == 0;
79 if is_even != expected_even {
80 let peer_role = match self.role {
81 Role::Client => Role::Server,
82 Role::Server => Role::Client,
83 };
84 return Err(RequestIdError::WrongParity(id, peer_role));
85 }
86 if id > self.max_id {
87 return Err(RequestIdError::ExceedsMax(id, self.max_id));
88 }
89 Ok(())
90 }
91
92 pub fn is_blocked(&self) -> bool {
94 self.max_id == 0 || self.next_id > self.max_id
95 }
96
97 pub fn max_id(&self) -> u64 {
99 self.max_id
100 }
101}