cargo/util/network/mod.rs
1//! Utilities for networking.
2
3use std::net::Ipv4Addr;
4use std::net::Ipv6Addr;
5use std::net::SocketAddr;
6use std::net::SocketAddrV4;
7use std::net::SocketAddrV6;
8use std::task::Poll;
9
10pub mod http;
11pub mod proxy;
12pub mod retry;
13pub mod sleep;
14
15/// LOCALHOST constants for both IPv4 and IPv6.
16pub const LOCALHOST: [SocketAddr; 2] = [
17 SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0)),
18 SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::LOCALHOST, 0, 0, 0)),
19];
20
21pub trait PollExt<T> {
22 fn expect(self, msg: &str) -> T;
23}
24
25impl<T> PollExt<T> for Poll<T> {
26 #[track_caller]
27 fn expect(self, msg: &str) -> T {
28 match self {
29 Poll::Ready(val) => val,
30 Poll::Pending => panic!("{}", msg),
31 }
32 }
33}
34
35/// When dynamically linked against libcurl, we want to ignore some failures
36/// when using old versions that don't support certain features.
37#[macro_export]
38macro_rules! try_old_curl {
39 ($e:expr, $msg:expr) => {
40 let result = $e;
41 if cfg!(target_os = "macos") {
42 if let Err(e) = result {
43 ::tracing::warn!(target: "network", "ignoring libcurl {} error: {}", $msg, e);
44 }
45 } else {
46 use ::anyhow::Context;
47 result.with_context(|| {
48 ::anyhow::format_err!("failed to enable {}, is curl not built right?", $msg)
49 })?;
50 }
51 };
52}
53
54/// Enable HTTP/2 and pipewait to be used as it'll allow true multiplexing
55/// which makes downloads much faster.
56///
57/// Currently Cargo requests the `http2` feature of the `curl` crate which
58/// means it should always be built in. On OSX, however, we ship cargo still
59/// linked against the system libcurl. Building curl with ALPN support for
60/// HTTP/2 requires newer versions of OSX (the SecureTransport API) than we
61/// want to ship Cargo for. By linking Cargo against the system libcurl then
62/// older curl installations won't use HTTP/2 but newer ones will. All that to
63/// basically say we ignore errors here on OSX, but consider this a fatal error
64/// to not activate HTTP/2 on all other platforms.
65///
66/// `pipewait` is an option which indicates that if there's a bunch of parallel
67/// requests to the same host they all wait until the pipelining status of the
68/// host is known. This means that we won't initiate dozens of connections but
69/// rather only one. Once the main one is opened we realized that pipelining is
70/// possible and multiplexing is possible. All in all this reduces the number
71/// of connections down to a more manageable state.
72#[macro_export]
73macro_rules! try_old_curl_http2_pipewait {
74 ($multiplexing:expr, $handle:expr) => {
75 if $multiplexing {
76 $crate::try_old_curl!($handle.http_version(curl::easy::HttpVersion::V2), "HTTP/2");
77 } else {
78 $handle.http_version(curl::easy::HttpVersion::V11)?;
79 }
80 $crate::try_old_curl!($handle.pipewait(true), "pipewait");
81 };
82}