Skip to main content

zlayer_proxy/stream/
config.rs

1//! Configuration types for stream (L4) proxy
2
3use serde::{Deserialize, Serialize};
4use std::time::Duration;
5
6/// Configuration for a TCP listener
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct TcpListenerConfig {
9    /// Listen port (proxy binds to 0.0.0.0:{port})
10    pub port: u16,
11
12    /// Protocol hint for metrics/logging (e.g., "postgresql", "mongodb", "minecraft")
13    #[serde(default)]
14    pub protocol_hint: Option<String>,
15
16    /// Enable TLS termination (auto-provision cert)
17    #[serde(default)]
18    pub tls: bool,
19
20    /// Enable PROXY protocol for passing client IP to backend
21    #[serde(default)]
22    pub proxy_protocol: bool,
23}
24
25/// Configuration for a UDP listener
26#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct UdpListenerConfig {
28    /// Listen port
29    pub port: u16,
30
31    /// Protocol hint for metrics/logging (e.g., "source-engine", "game-generic")
32    #[serde(default)]
33    pub protocol_hint: Option<String>,
34
35    /// Session timeout override (default uses global `udp_session_timeout`)
36    #[serde(default, with = "optional_duration_serde")]
37    pub session_timeout: Option<Duration>,
38}
39
40/// Default UDP session timeout (60 seconds)
41pub const DEFAULT_UDP_SESSION_TIMEOUT: Duration = Duration::from_secs(60);
42
43/// Serde helper for optional Duration serialization
44mod optional_duration_serde {
45    use serde::{Deserialize, Deserializer, Serialize, Serializer};
46    use std::time::Duration;
47
48    #[allow(clippy::ref_option)]
49    pub fn serialize<S>(value: &Option<Duration>, serializer: S) -> Result<S::Ok, S::Error>
50    where
51        S: Serializer,
52    {
53        match value {
54            Some(d) => d.as_secs().serialize(serializer),
55            None => serializer.serialize_none(),
56        }
57    }
58
59    pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Duration>, D::Error>
60    where
61        D: Deserializer<'de>,
62    {
63        let opt: Option<u64> = Option::deserialize(deserializer)?;
64        Ok(opt.map(Duration::from_secs))
65    }
66}