surge_ping/
config.rs

1use std::{net::SocketAddr, num::NonZeroU32};
2
3use socket2::{SockAddr, Type};
4
5use crate::ICMP;
6
7/// Config is the packaging of various configurations of `sockets`. If you want to make
8/// some `set_socket_opt` and other modifications, please define and implement them in `Config`.
9#[derive(Debug)]
10pub struct Config {
11    pub sock_type_hint: Type,
12    pub kind: ICMP,
13    pub bind: Option<SockAddr>,
14    pub interface: Option<String>,
15    pub interface_index: Option<NonZeroU32>,
16    pub ttl: Option<u32>,
17    pub fib: Option<u32>,
18}
19
20impl Default for Config {
21    fn default() -> Self {
22        Self {
23            sock_type_hint: Type::DGRAM,
24            kind: ICMP::default(),
25            bind: None,
26            interface: None,
27            interface_index: None,
28            ttl: None,
29            fib: None,
30        }
31    }
32}
33
34impl Config {
35    /// A structure that can be specially configured for socket.
36    pub fn new() -> Self {
37        Self::default()
38    }
39
40    pub fn builder() -> ConfigBuilder {
41        ConfigBuilder::default()
42    }
43}
44
45#[derive(Debug)]
46pub struct ConfigBuilder {
47    sock_type_hint: Type,
48    kind: ICMP,
49    bind: Option<SockAddr>,
50    interface: Option<String>,
51    interface_index: Option<NonZeroU32>,
52    ttl: Option<u32>,
53    fib: Option<u32>,
54}
55
56impl Default for ConfigBuilder {
57    fn default() -> Self {
58        Self {
59            sock_type_hint: Type::DGRAM,
60            kind: ICMP::default(),
61            bind: None,
62            interface: None,
63            interface_index: None,
64            ttl: None,
65            fib: None,
66        }
67    }
68}
69
70impl ConfigBuilder {
71    /// Binds this socket to the specified address.
72    ///
73    /// This function directly corresponds to the `bind(2)` function on Windows
74    /// and Unix.
75    pub fn bind(mut self, bind: SocketAddr) -> Self {
76        self.bind = Some(SockAddr::from(bind));
77        self
78    }
79
80    /// Sets the value for the `SO_BINDTODEVICE` option on this socket.
81    ///
82    /// If a socket is bound to an interface, only packets received from that
83    /// particular interface are processed by the socket. Note that this only
84    /// works for some socket types, particularly `AF_INET` sockets.
85    pub fn interface(mut self, interface: &str) -> Self {
86        self.interface = Some(interface.to_string());
87        self
88    }
89
90    /// Sets the value for the `IP_BOUND_IF`, `IPV6_BOUND_IF` or `SO_BINDTOIFINDEX` option on this socket depending on the platform and IP address family.
91    pub fn interface_index(mut self, interface_index: NonZeroU32) -> Self {
92        self.interface_index = Some(interface_index);
93        self
94    }
95
96    /// Set the value of the `IP_TTL` option for this socket.
97    ///
98    /// This value sets the time-to-live field that is used in every packet sent
99    /// from this socket.
100    pub fn ttl(mut self, ttl: u32) -> Self {
101        self.ttl = Some(ttl);
102        self
103    }
104
105    pub fn fib(mut self, fib: u32) -> Self {
106        self.fib = Some(fib);
107        self
108    }
109
110    /// Identify which ICMP the socket handles.(default: ICMP::V4)
111    pub fn kind(mut self, kind: ICMP) -> Self {
112        self.kind = kind;
113        self
114    }
115
116    /// Try to open the socket with provided at first (DGRAM or RAW)
117    pub fn sock_type_hint(mut self, typ: Type) -> Self {
118        self.sock_type_hint = typ;
119        self
120    }
121
122    pub fn build(self) -> Config {
123        Config {
124            sock_type_hint: self.sock_type_hint,
125            kind: self.kind,
126            bind: self.bind,
127            interface: self.interface,
128            interface_index: self.interface_index,
129            ttl: self.ttl,
130            fib: self.fib,
131        }
132    }
133}