Skip to content

Commit fc7ae2d

Browse files
authored
test: replace net2 dependency with socket2 (#635)
The proxy's integration tests depend on the `net2` crate, which has been deprecated and replaced by `socket2`. Since `net2` is no longer actively maintained, `cargo audit` will warn us about it, so we should replace it with `socket2`. While I was making this change, I was curious why we were manually constructing and binding these sockets at all, rather than just using `tokio::net::TcpListener::bind`. After some archaeology, I determined that this was added in linkerd/linkerd2#952, which added a test that requires a delay between when a socket is _bound_ and when it starts _listening_. `tokio::net::TcpListener::bind` (as well as the `std::net` version) perform these operations together. Since this wasn't obvious from the test code, I went ahead and moved the new `socket2` version of this into a pair of functions, with comments explaining why we didn't just use `tokio::net`. Fixes linkerd/linkerd2#4891
1 parent 487e85e commit fc7ae2d

File tree

6 files changed

+53
-23
lines changed

6 files changed

+53
-23
lines changed

Cargo.lock

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -717,9 +717,9 @@ checksum = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
717717

718718
[[package]]
719719
name = "libc"
720-
version = "0.2.65"
720+
version = "0.2.76"
721721
source = "registry+https://github.com/rust-lang/crates.io-index"
722-
checksum = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8"
722+
checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3"
723723

724724
[[package]]
725725
name = "libmimalloc-sys"
@@ -775,7 +775,6 @@ dependencies = [
775775
"linkerd2-metrics",
776776
"linkerd2-opencensus",
777777
"linkerd2-proxy-api",
778-
"net2",
779778
"quickcheck",
780779
"regex 1.3.9",
781780
"ring",
@@ -910,11 +909,11 @@ dependencies = [
910909
"linkerd2-app-core",
911910
"linkerd2-metrics",
912911
"linkerd2-proxy-api",
913-
"net2",
914912
"quickcheck",
915913
"regex 0.1.80",
916914
"ring",
917915
"rustls",
916+
"socket2",
918917
"tokio",
919918
"tokio-rustls",
920919
"tonic",
@@ -2138,9 +2137,9 @@ dependencies = [
21382137

21392138
[[package]]
21402139
name = "redox_syscall"
2141-
version = "0.1.37"
2140+
version = "0.1.57"
21422141
source = "registry+https://github.com/rust-lang/crates.io-index"
2143-
checksum = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd"
2142+
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
21442143

21452144
[[package]]
21462145
name = "regex"
@@ -2339,12 +2338,13 @@ checksum = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc"
23392338

23402339
[[package]]
23412340
name = "socket2"
2342-
version = "0.3.5"
2341+
version = "0.3.12"
23432342
source = "registry+https://github.com/rust-lang/crates.io-index"
2344-
checksum = "ff606e0486e88f5fc6cfeb3966e434fb409abbc7a3ab495238f70a1ca97f789d"
2343+
checksum = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918"
23452344
dependencies = [
23462345
"cfg-if",
23472346
"libc",
2347+
"redox_syscall",
23482348
"winapi 0.3.8",
23492349
]
23502350

linkerd/app/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ http = "0.2"
3939
hyper = "0.13.7"
4040
linkerd2-metrics = { path = "../metrics", features = ["test_util"] }
4141
linkerd2-proxy-api = { git = "https://github.com/linkerd/linkerd2-proxy-api", tag = "v0.1.13", features = ["arbitrary"] }
42-
net2 = "0.2"
4342
quickcheck = { version = "0.9", default-features = false }
4443
ring = "0.16"
4544
rustls = "0.17"

linkerd/app/integration/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ linkerd2-app-core = { path = "../core", features = ["mock-orig-dst"] }
2929
linkerd2-metrics = { path = "../../metrics", features = ["test_util"] }
3030
linkerd2-proxy-api = { git = "https://github.com/linkerd/linkerd2-proxy-api", tag = "v0.1.13", features = ["arbitrary"] }
3131
regex = "0.1"
32-
net2 = "0.2"
32+
socket2 = "0.3.12"
3333
quickcheck = { version = "0.9", default-features = false }
3434
ring = "0.16"
3535
rustls = "0.17"

linkerd/app/integration/src/controller.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -333,17 +333,16 @@ where
333333
B::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
334334
B::Data: Send + 'static,
335335
{
336-
let addr = SocketAddr::from(([127, 0, 0, 1], 0));
337-
let listener = net2::TcpBuilder::new_v4().expect("Tcp::new_v4");
338-
listener.bind(addr).expect("Tcp::bind");
339-
let addr = listener.local_addr().expect("Tcp::local_addr");
340-
let listener = listener.listen(1024).expect("listen");
341-
342336
let (listening_tx, listening_rx) = tokio::sync::oneshot::channel();
343337
let (drain_signal, drain) = drain::channel();
338+
339+
// Bind an ephemeral port but do not start listening yet.
340+
let (sock, addr) = crate::bind_ephemeral();
341+
344342
let task = tokio::spawn(
345343
cancelable(drain.clone(), async move {
346-
let mut listener = tokio::net::TcpListener::from_std(listener)?;
344+
// Start listening on the socket.
345+
let mut listener = crate::listen(sock);
347346
let mut listening_tx = Some(listening_tx);
348347

349348
if let Some(delay) = delay {

linkerd/app/integration/src/lib.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub use http::{HeaderMap, Request, Response, StatusCode};
1414
pub use http_body::Body as HttpBody;
1515
pub use linkerd2_app as app;
1616
pub use linkerd2_app_core::drain;
17+
use socket2::Socket;
1718
pub use std::collections::HashMap;
1819
use std::fmt;
1920
pub use std::future::Future;
@@ -286,3 +287,35 @@ pub async fn cancelable<E: Send + 'static>(
286287
}
287288
}
288289
}
290+
291+
/// Binds a socket to an ephemeral port without starting listening on it.
292+
///
293+
/// Some tests require us to introduce a delay between binding the server
294+
/// socket and listening on it. However, `tokio::net`'s
295+
/// `TcpListener::bind` function both binds the socket _and_ starts
296+
/// listening on it, so we can't just use that. Instead, we must manually
297+
/// construct the socket using `socket2`'s lower-level interface to libc
298+
/// socket APIs, and _then_ convert it into a Tokio `TcpListener`.
299+
pub(crate) fn bind_ephemeral() -> (Socket, SocketAddr) {
300+
use socket2::{Domain, Protocol, Type};
301+
302+
let addr = SocketAddr::from(([127, 0, 0, 1], 0));
303+
let sock =
304+
Socket::new(Domain::ipv4(), Type::stream(), Some(Protocol::tcp())).expect("Socket::new");
305+
sock.bind(&addr.into()).expect("Socket::bind");
306+
let addr = sock
307+
.local_addr()
308+
.expect("Socket::local_addr")
309+
.as_std()
310+
.expect("must be AF_INET");
311+
(sock, addr)
312+
}
313+
314+
/// Start listening on a socket previously bound using `socket2`, returning a
315+
/// Tokio `TcpListener`.
316+
pub(crate) fn listen(sock: Socket) -> TcpListener {
317+
sock.listen(1024)
318+
.expect("socket should be able to start listening");
319+
TcpListener::from_std(sock.into_tcp_listener())
320+
.expect("socket should be able to set nonblocking")
321+
}

linkerd/app/integration/src/server.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -201,10 +201,8 @@ impl Server {
201201
let srv_conn_count = Arc::clone(&conn_count);
202202
let version = self.version;
203203

204-
let addr = SocketAddr::from(([127, 0, 0, 1], 0));
205-
let listener = net2::TcpBuilder::new_v4().expect("Tcp::new_v4");
206-
listener.bind(addr).expect("Tcp::bind");
207-
let addr = listener.local_addr().expect("Tcp::local_addr");
204+
// Bind an ephemeral port but do not start listening yet.
205+
let (sock, addr) = crate::bind_ephemeral();
208206

209207
let (drain_signal, drain) = drain::channel();
210208
let tls_config = self.tls.clone();
@@ -223,8 +221,9 @@ impl Server {
223221
let _ = listening_tx.take().unwrap().send(());
224222
delay.await;
225223
}
226-
let listener = listener.listen(1024).expect("Tcp::listen");
227-
let mut listener = TcpListener::from_std(listener).expect("from_std");
224+
225+
// After the delay, start listening on the socket.
226+
let mut listener = crate::listen(sock);
228227

229228
if let Some(listening_tx) = listening_tx {
230229
let _ = listening_tx.send(());

0 commit comments

Comments
 (0)