o_sfu_protocol/core/
request_tracker.rs1use std::mem;
4
5use super::{
6 Command, Commands, PendingRequestKind,
7 timers::{REQUEST_TIMEOUT_TIMER_BASE, RequestTimeoutId},
8};
9use crate::signaling::RequestId;
10
11#[derive(Debug, Clone, PartialEq, Eq)]
12struct PendingRequestState {
13 request_id: RequestId,
14 kind: PendingRequestKind,
15 timeout_timer_id: RequestTimeoutId,
16}
17
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub(super) struct PendingRequestStart {
20 pub(super) request_id: RequestId,
21 pub(super) timeout_timer_id: RequestTimeoutId,
22}
23
24#[derive(Debug, Clone, PartialEq, Eq)]
26pub(super) struct RequestTracker {
27 next_request_counter: u64,
28 next_timeout_timer_id: RequestTimeoutId,
29 pending_requests: Vec<PendingRequestState>,
30}
31
32impl Default for RequestTracker {
33 fn default() -> Self {
34 Self::new()
35 }
36}
37
38impl RequestTracker {
39 pub(super) const fn new() -> Self {
40 Self {
41 next_request_counter: 0,
42 next_timeout_timer_id: REQUEST_TIMEOUT_TIMER_BASE,
43 pending_requests: Vec::new(),
44 }
45 }
46
47 pub(super) fn try_begin(&mut self, kind: PendingRequestKind) -> Option<PendingRequestStart> {
48 if self
49 .pending_requests
50 .iter()
51 .any(|pending_request| pending_request.kind == kind)
52 {
53 return None;
54 }
55 let request_id = self.allocate_request_id();
56 let timeout_timer_id = self.allocate_timeout_timer_id();
57 self.pending_requests.push(PendingRequestState {
58 request_id: request_id.clone(),
59 kind,
60 timeout_timer_id,
61 });
62 Some(PendingRequestStart {
63 request_id,
64 timeout_timer_id,
65 })
66 }
67
68 pub(super) fn resolve_response(
69 &mut self,
70 response_to: &RequestId,
71 expected_kind: PendingRequestKind,
72 ok: bool,
73 ) -> Commands {
74 let Some(index) = self.pending_requests.iter().position(|pending_request| {
75 pending_request.request_id == *response_to && pending_request.kind == expected_kind
76 }) else {
77 return Vec::new();
78 };
79 vec![complete_pending_request(
80 self.pending_requests.remove(index),
81 ok,
82 )]
83 }
84
85 pub(super) fn resolve_timeout(&mut self, timeout_id: RequestTimeoutId) -> Option<Commands> {
86 let index = self
87 .pending_requests
88 .iter()
89 .position(|pending_request| pending_request.timeout_timer_id == timeout_id)?;
90 Some(vec![complete_pending_request(
91 self.pending_requests.remove(index),
92 false,
93 )])
94 }
95
96 pub(super) fn clear(&mut self) {
97 self.pending_requests.clear();
98 }
99
100 pub(super) fn fail_all(&mut self) -> Commands {
102 mem::take(&mut self.pending_requests)
103 .into_iter()
104 .map(|pending_request| complete_pending_request(pending_request, false))
105 .collect()
106 }
107
108 fn allocate_request_id(&mut self) -> RequestId {
109 let request_id = RequestId::new(self.next_request_counter.to_string());
110 self.next_request_counter = self.next_request_counter.saturating_add(1);
111 request_id
112 }
113
114 fn allocate_timeout_timer_id(&mut self) -> RequestTimeoutId {
115 let timer_id = self.next_timeout_timer_id;
116 self.next_timeout_timer_id = timer_id.next();
117 timer_id
118 }
119}
120
121fn complete_pending_request(pending_request: PendingRequestState, ok: bool) -> Command {
122 Command::CompletePendingRequest {
123 request_id: pending_request.request_id,
124 timeout_timer_id: pending_request.timeout_timer_id.raw(),
125 ok,
126 }
127}