1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#[cfg_attr(feature = "clap", derive(clap::Args))]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[allow(clippy::struct_excessive_bools, clippy::doc_markdown)]
#[derive(Debug, Default)]
#[non_exhaustive]
/// User options that supplement listening address.
///
/// With `clap` crate feature, this struct can be `clap(flatten)`-ed directly into your primary command line parameters.
/// With `serde` crate feature, it supportes serialisation and deserialisation.
///
/// Create instances with `Default::default()` and modify available fields.
///
/// Non-relevant options are ignored by [`Listener::bind`].
///
/// All options are always available regardless of current platform, but may be hidden from --help.
///
/// Disabling related crate features removes them for good though.
pub struct UserOptions {
    #[cfg(feature = "unix_path_tools")]
    #[cfg_attr(docsrs_alt, doc(cfg(feature = "unix_path_tools")))]
    /// remove UNIX socket prior to binding to it
    #[cfg_attr(feature = "clap", clap(long))]
    #[cfg_attr(feature = "serde", serde(default))]
    #[cfg_attr(all(feature = "clap", not(unix)), clap(hide = true))]
    pub unix_listen_unlink: bool,

    #[cfg(feature = "unix_path_tools")]
    #[cfg_attr(docsrs_alt, doc(cfg(feature = "unix_path_tools")))]
    /// change filesystem mode of the newly bound UNIX socket to `owner`, `group` or `everybody`
    #[cfg_attr(feature = "clap", clap(long))]
    #[cfg_attr(all(feature = "clap", not(unix)), clap(hide = true))]
    #[cfg_attr(feature = "serde", serde(default))]
    pub unix_listen_chmod: Option<crate::UnixChmodVariant>,

    #[cfg(feature = "unix_path_tools")]
    #[cfg_attr(docsrs_alt, doc(cfg(feature = "unix_path_tools")))]
    /// change owner user of the newly bound UNIX socket to this numeric uid
    #[cfg_attr(feature = "clap", clap(long))]
    #[cfg_attr(feature = "serde", serde(default))]
    #[cfg_attr(all(feature = "clap", not(unix)), clap(hide = true))]
    pub unix_listen_uid: Option<u32>,

    #[cfg(feature = "unix_path_tools")]
    #[cfg_attr(docsrs_alt, doc(cfg(feature = "unix_path_tools")))]
    /// change owner group of the newly bound UNIX socket to this numeric uid
    #[cfg_attr(feature = "clap", clap(long))]
    #[cfg_attr(feature = "serde", serde(default))]
    #[cfg_attr(all(feature = "clap", not(unix)), clap(hide = true))]
    pub unix_listen_gid: Option<u32>,

    #[cfg(feature = "sd_listen")]
    #[cfg_attr(docsrs_alt, doc(cfg(feature = "sd_listen")))]
    /// ignore environment variables like LISTEN_PID or LISTEN_FDS and unconditionally use
    /// file descritor `3` as a socket in sd-listen or sd-listen-unix modes
    #[cfg_attr(feature = "clap", clap(long))]
    #[cfg_attr(feature = "serde", serde(default))]
    #[cfg_attr(all(feature = "clap", not(unix)), clap(hide = true))]
    pub sd_accept_ignore_environment: bool,

    #[cfg(feature = "socket_options")]
    #[cfg_attr(docsrs_alt, doc(cfg(feature = "socket_options")))]
    /// set SO_KEEPALIVE settings for each accepted TCP connection.
    ///
    /// Value is a colon-separated triplet of time_ms:count:interval_ms, each of which is optional.
    #[cfg_attr(feature = "clap", clap(long))]
    #[cfg_attr(feature = "serde", serde(default))]
    pub tcp_keepalive: Option<crate::TcpKeepaliveParams>,

    #[cfg(feature = "socket_options")]
    #[cfg_attr(docsrs_alt, doc(cfg(feature = "socket_options")))]
    /// Try to set SO_REUSEPORT, so that multiple processes can accept connections from the same port
    /// in a round-robin fashion
    #[cfg_attr(feature = "clap", clap(long))]
    #[cfg_attr(feature = "serde", serde(default))]
    pub tcp_reuse_port: bool,

    #[cfg(feature = "socket_options")]
    #[cfg_attr(docsrs_alt, doc(cfg(feature = "socket_options")))]
    /// Set socket's SO_RCVBUF value.
    #[cfg_attr(feature = "clap", clap(long))]
    #[cfg_attr(feature = "serde", serde(default))]
    pub recv_buffer_size: Option<usize>,

    #[cfg(feature = "socket_options")]
    #[cfg_attr(docsrs_alt, doc(cfg(feature = "socket_options")))]
    /// Set socket's SO_SNDBUF value.
    #[cfg_attr(feature = "clap", clap(long))]
    #[cfg_attr(feature = "serde", serde(default))]
    pub send_buffer_size: Option<usize>,

    #[cfg(feature = "socket_options")]
    #[cfg_attr(docsrs_alt, doc(cfg(feature = "socket_options")))]
    /// Set socket's IPV6_V6ONLY to true, to avoid receiving IPv4 connections on IPv6 socket.
    #[cfg_attr(feature = "clap", clap(long))]
    #[cfg_attr(feature = "serde", serde(default))]
    pub tcp_only_v6: bool,

    #[cfg(feature = "socket_options")]
    #[cfg_attr(docsrs_alt, doc(cfg(feature = "socket_options")))]
    /// Maximum number of pending unaccepted connections
    #[cfg_attr(feature = "clap", clap(long))]
    #[cfg_attr(feature = "serde", serde(default))]
    pub tcp_listen_backlog: Option<u32>,
}

/// Listener options that are supposed to be hard coded in the code
/// (not configurable by user)
#[non_exhaustive]
#[derive(Debug, Default, Clone, Copy)]
pub struct SystemOptions {
    /// Wait for one second and retry if accepting connections fail (for reasons unrelated to the connections themselves),
    /// assuming it is file descriptor number exhaustion, which may be temporary
    pub sleep_on_errors: bool,

    /// Set TCP_NODELAY on accepted TCP sockets. Does not affect other socket types.
    ///
    /// This field is available even without `socket_options` crate feature.
    pub nodelay: bool,
}