Skip to main content

leyline/tcp/
mod.rs

1use std::sync::Mutex;
2
3use serde::Deserialize;
4use socket2::Socket;
5
6mod platform;
7
8#[derive(Debug, Clone, Default, PartialEq, Eq, Deserialize)]
9#[non_exhaustive]
10pub struct TcpProfile {
11    pub ttl: u32,
12    pub mss: u32,
13    pub window_size: u32,
14    pub df: bool,
15    pub window_scale: u32,
16    pub no_delay: bool,
17    pub options: Vec<u8>,
18}
19
20impl TcpProfile {
21    pub(crate) fn apply(&self, socket: &Socket, is_v6: bool) {
22        if self.ttl > 0 {
23            let result = if is_v6 {
24                socket.set_unicast_hops_v6(self.ttl)
25            } else {
26                socket.set_ttl_v4(self.ttl)
27            };
28            if let Err(e) = result {
29                log_once(if is_v6 { "IPV6_UNICAST_HOPS" } else { "IP_TTL" }, &e);
30            }
31        }
32
33        if self.no_delay
34            && let Err(e) = socket.set_tcp_nodelay(true)
35        {
36            log_once("TCP_NODELAY", &e);
37        }
38
39        platform::apply_platform_options(socket, self, is_v6);
40    }
41}
42
43static LOGGED: Mutex<Vec<&'static str>> = Mutex::new(Vec::new());
44
45fn log_once(option: &'static str, err: &std::io::Error) {
46    let mut logged = crate::util::lock(&LOGGED);
47    if !logged.contains(&option) {
48        logged.push(option);
49        tracing::warn!(option, error = %err, "setsockopt failed (non-fatal)");
50    }
51}
52
53#[cfg(test)]
54mod tests;