1use alloc::collections::VecDeque;
9use alloc::sync::Arc;
10#[cfg(test)]
11use alloc::vec::Vec;
12use core::fmt::Debug;
13use core::hash::Hash;
14use core::ops::DerefMut;
15
16use assert_matches::assert_matches;
17use derivative::Derivative;
18use netstack3_base::Inspector;
19use netstack3_base::sync::Mutex;
20use netstack3_hashmap::HashMap;
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
24pub enum AcceptQueueChange {
25 ConnectionAdded {
27 was_empty: bool,
29 },
30 ConnectionRemoved {
32 is_empty: bool,
34 },
35}
36
37pub trait ListenerNotifier {
40 fn accept_queue_changed(&mut self, change: AcceptQueueChange);
42}
43
44#[derive(Debug, Derivative)]
50#[derivative(Clone(bound = ""))]
51pub struct AcceptQueue<S, R, N>(Arc<Mutex<AcceptQueueInner<S, R, N>>>);
52
53#[cfg(test)]
54impl<S, R, N> PartialEq for AcceptQueue<S, R, N>
55where
56 AcceptQueueInner<S, R, N>: PartialEq,
57{
58 fn eq(&self, Self(other): &Self) -> bool {
59 let Self(inner) = self;
60 if Arc::ptr_eq(other, inner) {
61 return true;
62 }
63 let guard = inner.lock();
64 let other_guard = other.lock();
65 (&*guard).eq(&*other_guard)
66 }
67}
68
69#[cfg(test)]
70impl<S, R, N> Eq for AcceptQueue<S, R, N> where Self: PartialEq {}
71
72#[derive(Debug)]
73#[cfg_attr(test, derive(Eq, PartialEq))]
74enum EntryState {
75 Pending,
76 Ready,
77}
78
79#[derive(Debug)]
80#[cfg_attr(test, derive(Derivative))]
81#[cfg_attr(
82 test,
83 derivative(PartialEq(bound = "S: Hash + Clone + Eq + PartialEq, R: PartialEq, N: PartialEq"))
84)]
85struct AcceptQueueInner<S, R, N> {
86 ready_queue: VecDeque<(S, R)>,
87 all_sockets: HashMap<S, EntryState>,
88 notifier: Option<N>,
89}
90
91impl<S, R, N> AcceptQueue<S, R, N>
92where
93 S: Hash + Clone + Eq + PartialEq + Debug,
94 N: ListenerNotifier,
95{
96 pub(crate) fn new(notifier: N) -> Self {
98 Self(Arc::new(Mutex::new(AcceptQueueInner::new(notifier))))
99 }
100
101 fn lock(&self) -> impl DerefMut<Target = AcceptQueueInner<S, R, N>> + '_ {
102 let Self(inner) = self;
103 inner.lock()
104 }
105
106 pub(crate) fn pop_ready(&self) -> Option<(S, R)> {
113 self.lock().pop_ready()
114 }
115
116 #[cfg(test)]
118 pub(crate) fn collect_pending(&self) -> Vec<S> {
119 self.lock().collect_pending()
120 }
121
122 pub(crate) fn push_pending(&self, pending: S) {
127 self.lock().push_pending(pending)
128 }
129
130 pub(crate) fn len(&self) -> usize {
132 self.lock().len()
133 }
134
135 #[cfg(test)]
137 pub(crate) fn ready_len(&self) -> usize {
138 self.lock().ready_len()
139 }
140
141 #[cfg(test)]
143 pub(crate) fn pending_len(&self) -> usize {
144 self.lock().pending_len()
145 }
146
147 pub(crate) fn notify_ready(&self, newly_ready: &S, ready_state: R) {
154 self.lock().notify_ready(newly_ready, ready_state)
155 }
156
157 pub(crate) fn remove(&self, entry: &S) {
161 self.lock().remove(entry)
162 }
163
164 pub(crate) fn close(&self) -> (impl Iterator<Item = S> + use<S, R, N>, N) {
169 self.lock().close()
170 }
171
172 pub(crate) fn is_closed(&self) -> bool {
174 self.lock().is_closed()
175 }
176
177 pub(crate) fn inspect<I: Inspector>(&self, inspector: &mut I) {
179 let inner = self.lock();
180 inspector.record_usize("NumReady", inner.ready_len());
181 inspector.record_usize("NumPending", inner.pending_len());
182 inspector.record_debug("Contents", &inner.all_sockets);
183 }
184}
185
186impl<S, R, N> AcceptQueueInner<S, R, N>
187where
188 S: Hash + Clone + Eq + PartialEq + Debug,
189 N: ListenerNotifier,
190{
191 fn new(notifier: N) -> Self {
192 Self {
193 ready_queue: Default::default(),
194 all_sockets: Default::default(),
195 notifier: Some(notifier),
196 }
197 }
198
199 fn pop_ready(&mut self) -> Option<(S, R)> {
200 let AcceptQueueInner { ready_queue, all_sockets, notifier } = self;
201 let (socket, ready_state) = ready_queue.pop_front()?;
202 assert_matches!(all_sockets.remove(&socket), Some(EntryState::Ready));
204 let notifier = notifier.as_mut().unwrap();
206 notifier.accept_queue_changed(AcceptQueueChange::ConnectionRemoved {
207 is_empty: ready_queue.is_empty(),
208 });
209 Some((socket, ready_state))
210 }
211
212 #[cfg(test)]
213 pub(crate) fn collect_pending(&self) -> Vec<S> {
214 let AcceptQueueInner { all_sockets, .. } = self;
215 all_sockets
216 .iter()
217 .filter_map(|(socket, state)| match state {
218 EntryState::Ready => None,
219 EntryState::Pending => Some(socket.clone()),
220 })
221 .collect()
222 }
223
224 fn push_pending(&mut self, pending: S) {
225 let AcceptQueueInner { all_sockets, notifier, .. } = self;
226 assert!(notifier.is_some());
229 assert_matches!(all_sockets.insert(pending, EntryState::Pending), None);
230 }
231
232 fn len(&self) -> usize {
233 let AcceptQueueInner { all_sockets, .. } = self;
234 all_sockets.len()
235 }
236
237 fn ready_len(&self) -> usize {
238 let AcceptQueueInner { ready_queue, .. } = self;
239 ready_queue.len()
240 }
241
242 fn pending_len(&self) -> usize {
243 let AcceptQueueInner { ready_queue, all_sockets, .. } = self;
244 all_sockets.len() - ready_queue.len()
245 }
246
247 fn notify_ready(&mut self, newly_ready: &S, ready_state: R) {
248 let AcceptQueueInner { ready_queue, all_sockets, notifier } = self;
249 let notifier = match notifier {
250 Some(notifier) => notifier,
251
252 None => {
253 debug_assert!(ready_queue.is_empty());
257 debug_assert!(all_sockets.is_empty());
258 return;
259 }
260 };
261 let entry = all_sockets
262 .get_mut(newly_ready)
263 .expect("attempted to notify ready entry that was not in queue");
264 let prev_state = core::mem::replace(entry, EntryState::Ready);
265 assert_matches!(prev_state, EntryState::Pending);
266 let was_empty = ready_queue.is_empty();
267 ready_queue.push_back((newly_ready.clone(), ready_state));
268 notifier.accept_queue_changed(AcceptQueueChange::ConnectionAdded { was_empty });
269 }
270
271 fn remove(&mut self, entry: &S) {
272 let AcceptQueueInner { ready_queue, all_sockets, notifier } = self;
273 let notifier = match notifier.as_mut() {
275 Some(notifier) => notifier,
276 None => {
277 debug_assert!(ready_queue.is_empty());
280 debug_assert!(all_sockets.is_empty());
281 return;
282 }
283 };
284
285 match all_sockets.remove(entry) {
286 Some(EntryState::Pending) | None => (),
287 Some(EntryState::Ready) => {
288 let before_len = ready_queue.len();
289 ready_queue.retain(|(s, _ready_data)| s != entry);
290 let after_len = ready_queue.len();
291 assert_eq!(after_len, before_len - 1);
293 notifier.accept_queue_changed(AcceptQueueChange::ConnectionRemoved {
294 is_empty: ready_queue.is_empty(),
295 });
296 }
297 }
298 }
299
300 fn close(&mut self) -> (impl Iterator<Item = S> + use<S, R, N>, N) {
301 let AcceptQueueInner { ready_queue, all_sockets, notifier } = self;
302 let notifier = notifier.take().expect("queue is already closed");
304 *ready_queue = Default::default();
308 let entries = core::mem::take(all_sockets);
311 (entries.into_keys(), notifier)
312 }
313
314 fn is_closed(&self) -> bool {
315 let AcceptQueueInner { notifier, .. } = self;
316 notifier.is_none()
317 }
318}
319
320#[cfg(test)]
321mod tests {
322 use assert_matches::assert_matches;
323 use netstack3_hashmap::HashSet;
324
325 use super::AcceptQueueChange;
326
327 #[test]
328 fn push_ready_pop() {
329 let mut queue = AcceptQueueInner::new(Notifier::default());
330 assert_eq!(queue.pop_ready(), None);
331 assert_eq!(queue.len(), 0);
332 assert_eq!(queue.ready_len(), 0);
333 assert_eq!(queue.pending_len(), 0);
334 assert_eq!(queue.clear_notifier(), None);
335
336 queue.push_pending(Socket(0));
337 assert_eq!(queue.pop_ready(), None);
338 assert_eq!(queue.len(), 1);
339 assert_eq!(queue.ready_len(), 0);
340 assert_eq!(queue.pending_len(), 1);
341 assert_eq!(queue.clear_notifier(), None);
342
343 queue.notify_ready(&Socket(0), Ready(2));
344 assert_eq!(queue.len(), 1);
345 assert_eq!(queue.ready_len(), 1);
346 assert_eq!(queue.pending_len(), 0);
347 assert_eq!(
348 queue.clear_notifier(),
349 Some(AcceptQueueChange::ConnectionAdded { was_empty: true })
350 );
351
352 queue.push_pending(Socket(1));
353 queue.notify_ready(&Socket(1), Ready(3));
354 assert_eq!(queue.len(), 2);
355 assert_eq!(queue.ready_len(), 2);
356 assert_eq!(queue.pending_len(), 0);
357 assert_eq!(
358 queue.clear_notifier(),
359 Some(AcceptQueueChange::ConnectionAdded { was_empty: false })
360 );
361
362 assert_eq!(queue.pop_ready(), Some((Socket(0), Ready(2))));
363 assert_eq!(
364 queue.clear_notifier(),
365 Some(AcceptQueueChange::ConnectionRemoved { is_empty: false })
366 );
367 assert_eq!(queue.len(), 1);
368 assert_eq!(queue.ready_len(), 1);
369 assert_eq!(queue.pending_len(), 0);
370
371 assert_eq!(queue.pop_ready(), Some((Socket(1), Ready(3))));
372 assert_eq!(
373 queue.clear_notifier(),
374 Some(AcceptQueueChange::ConnectionRemoved { is_empty: true })
375 );
376 assert_eq!(queue.len(), 0);
377 assert_eq!(queue.ready_len(), 0);
378 assert_eq!(queue.pending_len(), 0);
379 assert_eq!(queue.pop_ready(), None);
380 }
381
382 #[test]
383 fn close() {
384 let mut queue = AcceptQueueInner::new(Notifier::default());
385 let mut expect = HashSet::new();
386 for i in 0..3 {
387 let s = Socket(i);
388 queue.push_pending(s.clone());
389 assert!(expect.insert(s));
390 }
391 let (socks, _notifier) = queue.close();
392 let got = socks.collect::<HashSet<_>>();
393 assert_eq!(got, expect);
394
395 assert!(queue.is_closed());
396 assert_eq!(queue.len(), 0);
397 }
398
399 #[test]
400 fn remove() {
401 let mut queue = AcceptQueueInner::new(Notifier::default());
402 let s1 = Socket(1);
403 let s2 = Socket(2);
404 queue.push_pending(s1.clone());
405 queue.push_pending(s2.clone());
406 queue.notify_ready(&s2, Ready(2));
407 assert_eq!(queue.len(), 2);
408 assert_eq!(queue.ready_len(), 1);
409 assert_eq!(queue.pending_len(), 1);
410 assert_eq!(
411 queue.clear_notifier(),
412 Some(AcceptQueueChange::ConnectionAdded { was_empty: true })
413 );
414
415 queue.remove(&s1);
416 assert_eq!(queue.len(), 1);
417 assert_eq!(queue.ready_len(), 1);
418 assert_eq!(queue.pending_len(), 0);
419 assert_eq!(queue.clear_notifier(), None);
420
421 queue.remove(&s2);
422 assert_eq!(queue.len(), 0);
423 assert_eq!(queue.ready_len(), 0);
424 assert_eq!(queue.pending_len(), 0);
425 assert_eq!(
426 queue.clear_notifier(),
427 Some(AcceptQueueChange::ConnectionRemoved { is_empty: true })
428 );
429
430 queue.remove(&s1);
432 queue.remove(&s2);
433 assert_eq!(queue.len(), 0);
434 assert_eq!(queue.ready_len(), 0);
435 assert_eq!(queue.pending_len(), 0);
436 assert_eq!(queue.clear_notifier(), None);
437 }
438
439 #[derive(Default, Eq, PartialEq, Debug, Hash, Clone)]
440 struct Socket(usize);
441 #[derive(Default, Eq, PartialEq, Debug)]
442 struct Ready(usize);
443
444 #[derive(Default, Eq, PartialEq, Debug)]
445 struct Notifier(Option<AcceptQueueChange>);
446
447 type AcceptQueueInner = super::AcceptQueueInner<Socket, Ready, Notifier>;
448
449 impl AcceptQueueInner {
450 fn clear_notifier(&mut self) -> Option<AcceptQueueChange> {
451 let Self { notifier, .. } = self;
452 let Notifier(v) = notifier.as_mut().unwrap();
453 v.take()
454 }
455 }
456
457 impl super::ListenerNotifier for Notifier {
458 fn accept_queue_changed(&mut self, change: AcceptQueueChange) {
459 let Self(n) = self;
460 assert_matches!(n.replace(change), None);
461 }
462 }
463}