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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
//! Different implementations of a common async API for use in arti
//!
//! Currently only async_std, tokio and smol are provided.
pub
pub
pub
pub
pub
pub
pub
use warn_report;
/// Connection backlog size to use for `listen()` calls on IP sockets.
//
// How this was chosen:
//
// 1. The rust standard library uses a backlog of 128 for TCP sockets. This matches `SOMAXCONN` on
// most systems.
//
// 2. Mio (backend for tokio) previously used 1024. But they recently (confusingly) copied the logic
// from the standard library's unix socket implementation, which uses different values on
// different platforms. These values were tuned for unix sockets, so I think we should ignore
// them and mio's implementation here.
// https://github.com/tokio-rs/mio/pull/1896
//
// 3. Tor first tries using `INT_MAX`, and if that fails falls back to `SOMAXCONN` (using a global
// to remember if it did the fallback for future listen() calls; see `tor_listen`).
//
// 4. On supported platforms, if you use a backlog that is too large, the system will supposedly
// silently cap the value instead of failing.
//
// Linux:
// listen(2)
// > If the backlog argument is greater than the value in /proc/sys/net/core/somaxconn, then it
// > is silently capped to that value.
//
// FreeBSD:
// listen(2)
// > The sysctl(3) MIB variable kern.ipc.soacceptqueue specifies a hard limit on backlog; if a
// > value greater than kern.ipc.soacceptqueue or less than zero is specified, backlog is
// > silently forced to kern.ipc.soacceptqueue.
//
// OpenBSD:
// listen(2)
// > [BUGS] The backlog is currently limited (silently) to the value of the kern.somaxconn
// > sysctl, which defaults to 128.
//
// Windows:
// https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-listen
// > The backlog parameter is limited (silently) to a reasonable value as determined by the
// > underlying service provider. Illegal values are replaced by the nearest legal value.
//
// Mac OS:
// Archived listen(2) docs
// https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/listen.2.html
// > [BUGS] The backlog is currently limited (silently) to 128.
//
// 5. While the rust APIs take a `u32`, the libc API uses `int`. So we shouldn't use a value larger
// than `c_int::MAX`.
//
// 6. We should be careful not to set this too large, as supposedly some systems will truncate this to
// 16 bits. So for example a value of `65536` would cause a backlog of 1. But maybe they are just
// referring to systems where `int` is 16 bits?
// https://bugs.python.org/issue38699#msg357957
//
// Here we use `u16::MAX`. We assume that this will succeed on all supported platforms. Unlike tor,
// we do not try again with a smaller value since this doesn't seem to be needed on modern systems.
// We can add it if we find that it's needed.
//
// A value of `u16::MAX` is arguably too high, since a smaller value like 4096 would be large enough
// for legitimate traffic, and illegitimate traffic would be better handled by the kernel with
// something like SYN cookies. But it's easier for users to reduce the max using
// `/proc/sys/net/core/somaxconn` than to increase this max by recompiling arti.
const LISTEN_BACKLOG: i32 = u16MAX as i32;
/// Open a listening TCP socket.
///
/// The socket will be non-blocking, and the socket handle will be close-on-exec/non-inheritable.
/// Other socket options may also be set depending on the socket type and platform.
///
/// Historically we relied on the runtime to create a listening socket, but we need some specific
/// socket options set, and not all runtimes will behave the same. It's better for us to create the
/// socket with the options we need and with consistent behaviour across all runtimes. For example
/// if each runtime were using a different `listen()` backlog size, it might be difficult to debug
/// related issues.
pub
/// Stub replacement for tcp_listen on wasm32-unknown
pub
/// Helper: Implement an unreachable NetProvider<unix::SocketAddr> for a given runtime.
=>
}
pub use impl_unix_non_provider;