Skip to main content

openmoat_proxy/server/
limits.rs

1//! Bounds on what one client can make the proxy hold.
2
3use std::io::{self, ErrorKind};
4use std::time::{Duration, Instant};
5
6/// Bounds on what one client can make the proxy hold.
7#[derive(Debug, Clone)]
8pub struct Limits {
9    /// Largest request head, in bytes.
10    pub max_head_bytes: usize,
11    /// Time allowed for the request head, and for the `ClientHello` after it.
12    pub handshake_timeout: Duration,
13    /// A relayed connection with no bytes either way for this long is closed.
14    pub idle_timeout: Duration,
15    /// Time allowed to connect to the destination.
16    pub connect_timeout: Duration,
17    /// Connections served at once; more are answered 503 and closed. With
18    /// sessions, one session (or the connections not yet authenticated) may
19    /// hold at most half of them.
20    pub max_connections: usize,
21}
22
23impl Limits {
24    /// Refuse limits under which no connection could be served: a zero limit,
25    /// or a timeout too large to set a deadline with.
26    pub(super) fn check(&self) -> io::Result<()> {
27        let now = Instant::now();
28        let sizes = [
29            ("max_head_bytes", self.max_head_bytes),
30            ("max_connections", self.max_connections),
31        ];
32        let timeouts = [
33            ("handshake_timeout", self.handshake_timeout),
34            ("idle_timeout", self.idle_timeout),
35            ("connect_timeout", self.connect_timeout),
36        ];
37        let bad = sizes
38            .iter()
39            .find(|(_, n)| *n == 0)
40            .map(|(name, _)| name)
41            .or_else(|| {
42                timeouts
43                    .iter()
44                    .find(|(_, d)| d.is_zero() || now.checked_add(*d).is_none())
45                    .map(|(name, _)| name)
46            });
47        match bad {
48            Some(name) => Err(io::Error::new(
49                ErrorKind::InvalidInput,
50                format!("proxy limit `{name}` is zero or too large"),
51            )),
52            None => Ok(()),
53        }
54    }
55}
56
57impl Default for Limits {
58    fn default() -> Self {
59        Self {
60            max_head_bytes: 16 * 1024,
61            handshake_timeout: Duration::from_secs(10),
62            idle_timeout: Duration::from_mins(2),
63            connect_timeout: Duration::from_secs(10),
64            max_connections: 256,
65        }
66    }
67}