1#![doc = include_str!("../README.md")]
2
3use std::time::Duration;
4
5static CONNECTION_ATTEMPT_DELAY: Duration = Duration::from_millis(250);
6
7#[cfg(feature = "std-net")]
8mod std_net;
9#[cfg(feature = "std-net")]
10pub use std_net::connect;
11
12#[cfg(feature = "tokio")]
13pub mod tokio;
14
15#[cfg(feature = "async-std")]
16pub mod async_std;
17
18#[cfg(test)]
19mod test_utils {
20 use rand::{thread_rng, Rng};
21 use std::io::ErrorKind;
22 use std::io::Write;
23 use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, TcpListener};
24 use std::thread::JoinHandle;
25
26 fn listen<A: Into<IpAddr>>(addr: A) -> (TcpListener, IpAddr, u16) {
27 let addr: IpAddr = addr.into();
28 let tar_pit_port = std::env::var("HAPPY_EYEBALLS_TAR_PIT_PORT")
29 .ok()
30 .and_then(|s| u16::from_str_radix(&s, 10).ok());
31 loop {
32 let port: u16 = thread_rng().gen_range(49152..=65535);
34 if tar_pit_port == Some(port) {
35 continue;
36 }
37 match TcpListener::bind((addr, port)) {
38 Ok(listener) => return (listener, addr, port),
39 Err(err) if err.kind() == ErrorKind::AddrInUse => (),
40 Err(e) => panic!("TcpListener::bind({addr}, {port}) failed: {e}"),
41 }
42 }
43 }
44
45 fn serve<A: Into<IpAddr>>(addr: A) -> (JoinHandle<()>, IpAddr, u16) {
46 let (serve, addr, port) = listen(addr);
47 let data = format!("{addr}");
48 let handle = std::thread::spawn(move || {
49 for s in serve.incoming() {
50 s.unwrap().write_all(data.as_bytes()).unwrap();
51 }
52 });
53 (handle, addr, port)
54 }
55
56 pub fn serve_4() -> (JoinHandle<()>, IpAddr, u16) {
57 serve(Ipv4Addr::LOCALHOST)
58 }
59
60 pub fn serve_6() -> (JoinHandle<()>, IpAddr, u16) {
61 serve(Ipv6Addr::LOCALHOST)
62 }
63
64 pub fn tar_pit<A: Into<IpAddr>>(addr: A) -> ((), IpAddr, u16) {
65 let addr: IpAddr = addr.into();
66 let port = std::env::var("HAPPY_EYEBALLS_TAR_PIT_PORT").expect(
67 "\
68To test the tar pit, set the environment variable HAPPY_EYEBALLS_TAR_PIT_PORT \
69to the port number that is blackholed in IPv4 *and* IPv6.",
70 );
71 let port = u16::from_str_radix(&port, 10).unwrap();
72 ((), addr, port)
73 }
74}