actix_tls/connect/
info.rs1use std::{
4 collections::VecDeque,
5 fmt,
6 iter::{self, FromIterator as _},
7 mem,
8 net::{IpAddr, SocketAddr},
9};
10
11use super::{
12 connect_addrs::{ConnectAddrs, ConnectAddrsIter},
13 Host,
14};
15
16#[derive(Debug, PartialEq, Eq, Hash)]
20pub struct ConnectInfo<R> {
21 pub(crate) request: R,
22 pub(crate) port: u16,
23 pub(crate) addr: ConnectAddrs,
24 pub(crate) local_addr: Option<IpAddr>,
25}
26
27impl<R: Host> ConnectInfo<R> {
28 pub fn new(request: R) -> ConnectInfo<R> {
30 let port = request.port();
31
32 ConnectInfo {
33 request,
34 port: port.unwrap_or(0),
35 addr: ConnectAddrs::None,
36 local_addr: None,
37 }
38 }
39
40 pub fn with_addr(request: R, addr: SocketAddr) -> ConnectInfo<R> {
45 ConnectInfo {
46 request,
47 port: 0,
48 addr: ConnectAddrs::One(addr),
49 local_addr: None,
50 }
51 }
52
53 pub fn set_port(mut self, port: u16) -> Self {
57 self.port = port;
58 self
59 }
60
61 pub fn set_addr(mut self, addr: impl Into<Option<SocketAddr>>) -> Self {
63 self.addr = ConnectAddrs::from(addr.into());
64 self
65 }
66
67 pub fn set_addrs<I>(mut self, addrs: I) -> Self
69 where
70 I: IntoIterator<Item = SocketAddr>,
71 {
72 let mut addrs = VecDeque::from_iter(addrs);
73 self.addr = if addrs.len() < 2 {
74 ConnectAddrs::from(addrs.pop_front())
75 } else {
76 ConnectAddrs::Multi(addrs)
77 };
78 self
79 }
80
81 pub fn set_local_addr(mut self, addr: impl Into<IpAddr>) -> Self {
86 self.local_addr = Some(addr.into());
87 self
88 }
89
90 pub fn request(&self) -> &R {
92 &self.request
93 }
94
95 pub fn hostname(&self) -> &str {
97 self.request.hostname()
98 }
99
100 pub fn port(&self) -> u16 {
102 self.request.port().unwrap_or(self.port)
103 }
104
105 #[allow(clippy::implied_bounds_in_impls)]
122 pub fn addrs(
123 &self,
124 ) -> impl Iterator<Item = SocketAddr>
125 + ExactSizeIterator
126 + iter::FusedIterator
127 + Clone
128 + fmt::Debug
129 + '_ {
130 match self.addr {
131 ConnectAddrs::None => ConnectAddrsIter::None,
132 ConnectAddrs::One(addr) => ConnectAddrsIter::One(addr),
133 ConnectAddrs::Multi(ref addrs) => ConnectAddrsIter::Multi(addrs.iter()),
134 }
135 }
136
137 #[allow(clippy::implied_bounds_in_impls)]
154 pub fn take_addrs(
155 &mut self,
156 ) -> impl Iterator<Item = SocketAddr>
157 + ExactSizeIterator
158 + iter::FusedIterator
159 + Clone
160 + fmt::Debug
161 + 'static {
162 match mem::take(&mut self.addr) {
163 ConnectAddrs::None => ConnectAddrsIter::None,
164 ConnectAddrs::One(addr) => ConnectAddrsIter::One(addr),
165 ConnectAddrs::Multi(addrs) => ConnectAddrsIter::MultiOwned(addrs.into_iter()),
166 }
167 }
168}
169
170impl<R: Host> From<R> for ConnectInfo<R> {
171 fn from(addr: R) -> Self {
172 ConnectInfo::new(addr)
173 }
174}
175
176impl<R: Host> fmt::Display for ConnectInfo<R> {
177 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178 write!(f, "{}:{}", self.hostname(), self.port())
179 }
180}
181
182#[cfg(test)]
183mod tests {
184 use std::net::Ipv4Addr;
185
186 use super::*;
187
188 #[test]
189 fn test_addr_iter_multi() {
190 let localhost = SocketAddr::from((IpAddr::from(Ipv4Addr::LOCALHOST), 8080));
191 let unspecified = SocketAddr::from((IpAddr::from(Ipv4Addr::UNSPECIFIED), 8080));
192
193 let mut addrs = VecDeque::new();
194 addrs.push_back(localhost);
195 addrs.push_back(unspecified);
196
197 let mut iter = ConnectAddrsIter::Multi(addrs.iter());
198 assert_eq!(iter.next(), Some(localhost));
199 assert_eq!(iter.next(), Some(unspecified));
200 assert_eq!(iter.next(), None);
201
202 let mut iter = ConnectAddrsIter::MultiOwned(addrs.into_iter());
203 assert_eq!(iter.next(), Some(localhost));
204 assert_eq!(iter.next(), Some(unspecified));
205 assert_eq!(iter.next(), None);
206 }
207
208 #[test]
209 fn test_addr_iter_single() {
210 let localhost = SocketAddr::from((IpAddr::from(Ipv4Addr::LOCALHOST), 8080));
211
212 let mut iter = ConnectAddrsIter::One(localhost);
213 assert_eq!(iter.next(), Some(localhost));
214 assert_eq!(iter.next(), None);
215
216 let mut iter = ConnectAddrsIter::None;
217 assert_eq!(iter.next(), None);
218 }
219
220 #[test]
221 fn test_local_addr() {
222 let conn = ConnectInfo::new("hello").set_local_addr([127, 0, 0, 1]);
223 assert_eq!(
224 conn.local_addr.unwrap(),
225 IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))
226 )
227 }
228
229 #[test]
230 fn request_ref() {
231 let conn = ConnectInfo::new("hello");
232 assert_eq!(conn.request(), &"hello")
233 }
234
235 #[test]
236 fn set_connect_addr_into_option() {
237 let addr = SocketAddr::from(([127, 0, 0, 1], 4242));
238
239 let conn = ConnectInfo::new("hello").set_addr(None);
240 let mut addrs = conn.addrs();
241 assert!(addrs.next().is_none());
242
243 let conn = ConnectInfo::new("hello").set_addr(addr);
244 let mut addrs = conn.addrs();
245 assert_eq!(addrs.next().unwrap(), addr);
246
247 let conn = ConnectInfo::new("hello").set_addr(Some(addr));
248 let mut addrs = conn.addrs();
249 assert_eq!(addrs.next().unwrap(), addr);
250 }
251}