/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 | | } |