Skip to main content

quiche/
dgram.rs

1// Copyright (C) 2020, Cloudflare, Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8//     * Redistributions of source code must retain the above copyright notice,
9//       this list of conditions and the following disclaimer.
10//
11//     * Redistributions in binary form must reproduce the above copyright
12//       notice, this list of conditions and the following disclaimer in the
13//       documentation and/or other materials provided with the distribution.
14//
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
19// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27use crate::BufFactory;
28use crate::Error;
29use crate::Result;
30
31use std::collections::VecDeque;
32
33/// Keeps track of DATAGRAM frames.
34#[derive(Default)]
35pub struct DatagramQueue<F: BufFactory> {
36    queue: VecDeque<F::DgramBuf>,
37    queue_max_len: usize,
38    queue_bytes_size: usize,
39}
40
41impl<F: BufFactory> DatagramQueue<F> {
42    pub fn new(queue_max_len: usize) -> Self {
43        DatagramQueue {
44            queue: VecDeque::new(),
45            queue_bytes_size: 0,
46            queue_max_len,
47        }
48    }
49
50    pub fn push(&mut self, data: F::DgramBuf) -> Result<()> {
51        if self.is_full() {
52            return Err(Error::Done);
53        }
54
55        self.queue_bytes_size += data.as_ref().len();
56        self.queue.push_back(data);
57
58        Ok(())
59    }
60
61    pub fn peek_front_len(&self) -> Option<usize> {
62        self.queue.front().map(|d| d.as_ref().len())
63    }
64
65    pub fn peek_front_bytes(&self, buf: &mut [u8], len: usize) -> Result<usize> {
66        match self.queue.front() {
67            Some(d) => {
68                let len = std::cmp::min(len, d.as_ref().len());
69                if buf.len() < len {
70                    return Err(Error::BufferTooShort);
71                }
72
73                buf[..len].copy_from_slice(&d.as_ref()[..len]);
74                Ok(len)
75            },
76
77            None => Err(Error::Done),
78        }
79    }
80
81    pub fn pop(&mut self) -> Option<F::DgramBuf> {
82        if let Some(d) = self.queue.pop_front() {
83            self.queue_bytes_size =
84                self.queue_bytes_size.saturating_sub(d.as_ref().len());
85            return Some(d);
86        }
87
88        None
89    }
90
91    pub fn has_pending(&self) -> bool {
92        !self.queue.is_empty()
93    }
94
95    pub fn purge<FN: Fn(&[u8]) -> bool>(&mut self, f: FN) {
96        self.queue.retain(|d| !f(d.as_ref()));
97        self.queue_bytes_size = self
98            .queue
99            .iter()
100            .fold(0, |total, d| total + d.as_ref().len());
101    }
102
103    pub fn is_full(&self) -> bool {
104        self.len() == self.queue_max_len
105    }
106
107    pub fn is_empty(&self) -> bool {
108        self.len() == 0
109    }
110
111    pub fn len(&self) -> usize {
112        self.queue.len()
113    }
114
115    pub fn byte_size(&self) -> usize {
116        self.queue_bytes_size
117    }
118}