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