Coverage Report

Created: 2025-07-18 06:03

/rust/registry/src/index.crates.io-6f17d22bba15001f/cap-std-3.4.4/src/net/pool.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::net::{SocketAddr, TcpListener, TcpStream, ToSocketAddrs, UdpSocket};
2
use cap_primitives::net::no_socket_addrs;
3
use cap_primitives::{ipnet, AmbientAuthority};
4
use std::time::Duration;
5
use std::{io, net};
6
7
/// A pool of network addresses.
8
///
9
/// This does not directly correspond to anything in `std`, however its methods
10
/// correspond to the several functions in [`std::net`].
11
///
12
/// `Pool` implements `Clone`, which creates new independent entities that
13
/// carry the full authority of the originals. This means that in a borrow
14
/// of a `Pool`, the scope of the authority is not necessarily limited to
15
/// the scope of the borrow.
16
///
17
/// Similarly, the [`cap_net_ext::PoolExt`] class allows creating "binder"
18
/// and "connecter" objects which represent capabilities to bind and
19
/// connect to addresses.
20
///
21
/// [`cap_net_ext::PoolExt`]: https://docs.rs/cap-net-ext/latest/cap_net_ext/trait.PoolExt.html
22
#[derive(Clone, Default)]
23
pub struct Pool {
24
    cap: cap_primitives::net::Pool,
25
}
26
27
impl Pool {
28
    /// Construct a new empty pool.
29
0
    pub fn new() -> Self {
30
0
        Self {
31
0
            cap: cap_primitives::net::Pool::new(),
32
0
        }
33
0
    }
34
35
    /// Add addresses to the pool.
36
    ///
37
    /// # Ambient Authority
38
    ///
39
    /// This function allows ambient access to any IP address.
40
0
    pub fn insert<A: ToSocketAddrs>(
41
0
        &mut self,
42
0
        addrs: A,
43
0
        ambient_authority: AmbientAuthority,
44
0
    ) -> io::Result<()> {
45
0
        self.cap.insert(addrs, ambient_authority)
46
0
    }
47
48
    /// Add a specific [`net::SocketAddr`] to the pool.
49
    ///
50
    /// # Ambient Authority
51
    ///
52
    /// This function allows ambient access to any IP address.
53
0
    pub fn insert_socket_addr(
54
0
        &mut self,
55
0
        addr: net::SocketAddr,
56
0
        ambient_authority: AmbientAuthority,
57
0
    ) {
58
0
        self.cap.insert_socket_addr(addr, ambient_authority)
59
0
    }
60
61
    /// Add a range of network addresses, accepting any port, to the pool.
62
    ///
63
    /// Unlike `insert_ip_net`, this function grants access to any requested
64
    /// port.
65
    ///
66
    /// # Ambient Authority
67
    ///
68
    /// This function allows ambient access to any IP address.
69
0
    pub fn insert_ip_net_port_any(
70
0
        &mut self,
71
0
        ip_net: ipnet::IpNet,
72
0
        ambient_authority: AmbientAuthority,
73
0
    ) {
74
0
        self.cap.insert_ip_net_port_any(ip_net, ambient_authority)
75
0
    }
76
77
    /// Add a range of network addresses, accepting a range of ports, to the
78
    /// pool.
79
    ///
80
    /// This grants access to the port range starting at `ports_start` and,
81
    /// if `ports_end` is provided, ending before `ports_end`.
82
    ///
83
    /// # Ambient Authority
84
    ///
85
    /// This function allows ambient access to any IP address.
86
0
    pub fn insert_ip_net_port_range(
87
0
        &mut self,
88
0
        ip_net: ipnet::IpNet,
89
0
        ports_start: u16,
90
0
        ports_end: Option<u16>,
91
0
        ambient_authority: AmbientAuthority,
92
0
    ) {
93
0
        self.cap
94
0
            .insert_ip_net_port_range(ip_net, ports_start, ports_end, ambient_authority)
95
0
    }
96
97
    /// Add a range of network addresses with a specific port to the pool.
98
    ///
99
    /// # Ambient Authority
100
    ///
101
    /// This function allows ambient access to any IP address.
102
0
    pub fn insert_ip_net(
103
0
        &mut self,
104
0
        ip_net: ipnet::IpNet,
105
0
        port: u16,
106
0
        ambient_authority: AmbientAuthority,
107
0
    ) {
108
0
        self.cap.insert_ip_net(ip_net, port, ambient_authority)
109
0
    }
110
111
    /// Creates a new `TcpListener` which will be bound to the specified
112
    /// address.
113
    ///
114
    /// This corresponds to [`std::net::TcpListener::bind`].
115
    #[doc(alias = "bind")]
116
    #[inline]
117
0
    pub fn bind_tcp_listener<A: ToSocketAddrs>(&self, addr: A) -> io::Result<TcpListener> {
118
0
        let addrs = addr.to_socket_addrs()?;
119
120
0
        let mut last_err = None;
121
0
        for addr in addrs {
122
0
            self.cap.check_addr(&addr)?;
123
            // TODO: when compiling for WASI, use WASI-specific methods instead
124
0
            match net::TcpListener::bind(addr) {
125
0
                Ok(tcp_listener) => return Ok(TcpListener::from_std(tcp_listener)),
126
0
                Err(e) => last_err = Some(e),
127
            }
128
        }
129
0
        match last_err {
130
0
            Some(e) => Err(e),
131
0
            None => Err(no_socket_addrs()),
132
        }
133
0
    }
134
135
    /// Opens a TCP connection to a remote host.
136
    ///
137
    /// This corresponds to [`std::net::TcpStream::connect`].
138
    #[doc(alias = "connect")]
139
    #[inline]
140
0
    pub fn connect_tcp_stream<A: ToSocketAddrs>(&self, addr: A) -> io::Result<TcpStream> {
141
0
        let addrs = addr.to_socket_addrs()?;
142
143
0
        let mut last_err = None;
144
0
        for addr in addrs {
145
0
            self.cap.check_addr(&addr)?;
146
            // TODO: when compiling for WASI, use WASI-specific methods instead
147
0
            match net::TcpStream::connect(addr) {
148
0
                Ok(tcp_stream) => return Ok(TcpStream::from_std(tcp_stream)),
149
0
                Err(e) => last_err = Some(e),
150
            }
151
        }
152
0
        match last_err {
153
0
            Some(e) => Err(e),
154
0
            None => Err(no_socket_addrs()),
155
        }
156
0
    }
157
158
    /// Opens a TCP connection to a remote host with a timeout.
159
    ///
160
    /// This corresponds to [`std::net::TcpStream::connect_timeout`].
161
    #[doc(alias = "connect")]
162
    #[inline]
163
0
    pub fn connect_timeout_tcp_stream(
164
0
        &self,
165
0
        addr: &SocketAddr,
166
0
        timeout: Duration,
167
0
    ) -> io::Result<TcpStream> {
168
0
        self.cap.check_addr(addr)?;
169
0
        let tcp_stream = net::TcpStream::connect_timeout(addr, timeout)?;
170
0
        Ok(TcpStream::from_std(tcp_stream))
171
0
    }
172
173
    /// Creates a UDP socket from the given address.
174
    ///
175
    /// This corresponds to [`std::net::UdpSocket::bind`].
176
    #[doc(alias = "bind")]
177
    #[inline]
178
0
    pub fn bind_udp_socket<A: ToSocketAddrs>(&self, addr: A) -> io::Result<UdpSocket> {
179
0
        let addrs = addr.to_socket_addrs()?;
180
181
0
        let mut last_err = None;
182
0
        for addr in addrs {
183
0
            self.cap.check_addr(&addr)?;
184
0
            match net::UdpSocket::bind(addr) {
185
0
                Ok(udp_socket) => return Ok(UdpSocket::from_std(udp_socket)),
186
0
                Err(e) => last_err = Some(e),
187
            }
188
        }
189
0
        match last_err {
190
0
            Some(e) => Err(e),
191
0
            None => Err(no_socket_addrs()),
192
        }
193
0
    }
194
195
    /// Sends data on the socket to the given address. On success, returns the
196
    /// number of bytes written.
197
    ///
198
    /// This corresponds to [`std::net::UdpSocket::send_to`].
199
    #[doc(alias = "send_to")]
200
    #[inline]
201
0
    pub fn send_to_udp_socket_addr<A: ToSocketAddrs>(
202
0
        &self,
203
0
        udp_socket: &UdpSocket,
204
0
        buf: &[u8],
205
0
        addr: A,
206
0
    ) -> io::Result<usize> {
207
0
        let mut addrs = addr.to_socket_addrs()?;
208
209
        // `UdpSocket::send_to` only sends to the first address.
210
0
        let addr = addrs.next().ok_or_else(no_socket_addrs)?;
211
0
        self.cap.check_addr(&addr)?;
212
0
        udp_socket.std.send_to(buf, addr)
213
0
    }
214
215
    /// Connects this UDP socket to a remote address, allowing the `send` and
216
    /// `recv` syscalls to be used to send data and also applies filters to
217
    /// only receive data from the specified address.
218
    ///
219
    /// This corresponds to [`std::net::UdpSocket::connect`].
220
    #[doc(alias = "connect")]
221
    #[inline]
222
0
    pub fn connect_udp_socket<A: ToSocketAddrs>(
223
0
        &self,
224
0
        udp_socket: &UdpSocket,
225
0
        addr: A,
226
0
    ) -> io::Result<()> {
227
0
        let addrs = addr.to_socket_addrs()?;
228
229
0
        let mut last_err = None;
230
0
        for addr in addrs {
231
0
            self.cap.check_addr(&addr)?;
232
0
            match udp_socket.std.connect(addr) {
233
0
                Ok(()) => return Ok(()),
234
0
                Err(e) => last_err = Some(e),
235
            }
236
        }
237
0
        match last_err {
238
0
            Some(e) => Err(e),
239
0
            None => Err(no_socket_addrs()),
240
        }
241
0
    }
242
243
    /// This is for cap-net-ext.
244
    #[doc(hidden)]
245
0
    pub fn _pool(&self) -> &cap_primitives::net::Pool {
246
0
        &self.cap
247
0
    }
248
}