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