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