#[cfg(any(feature = "tcp", feature = "udp"))]
use std::net::{Ipv4Addr, SocketAddr};
use std::{
cell::Cell,
future::{Future, poll_fn},
time::Duration,
};
#[cfg(feature = "tcp")]
use socket2::{Domain, SockAddr, Socket, Type};
use crate::{Mode, Runtime};
#[cfg(feature = "tcp")]
mod tcp;
#[cfg(feature = "udp")]
mod udp;
#[cfg(all(feature = "unix", unix))]
mod unix;
macro_rules! in_both_modes {
($(#[$attr:meta])* fn $name:ident<$mode:ident>() $body:block) => {
$(#[$attr])*
mod $name {
use super::*;
#[test]
#[ntest::timeout(15000)]
fn local() {
run::<$crate::Local>();
}
#[test]
#[ntest::timeout(15000)]
fn shared() {
run::<$crate::Shared>();
}
fn run<$mode>()
where
$mode: $crate::Mode,
$body
}
};
}
use in_both_modes;
async fn after<M, F>(runtime: &Runtime<M>, future: F) -> F::Output
where
M: Mode,
F: Future,
{
runtime.sleep(DELAY).await;
future.await
}
fn counting_polls<'a, F>(polls: &'a Cell<usize>, future: F) -> impl Future<Output = F::Output> + 'a
where
F: Future + 'a,
{
let mut future = Box::pin(future);
poll_fn(move |cx| {
polls.set(polls.get() + 1);
future.as_mut().poll(cx)
})
}
const DELAY: Duration = Duration::from_millis(50);
#[cfg(any(feature = "tcp", all(feature = "unix", unix)))]
fn pattern(len: usize) -> Vec<u8> {
(0..len).map(|i| (i % 251) as u8).collect()
}
#[cfg(feature = "tcp")]
struct RefusedPort {
socket: Socket,
_listener: Socket,
}
#[cfg(feature = "tcp")]
impl RefusedPort {
fn new() -> Self {
let listener = bound(loopback());
listener.listen(1).expect("a bound socket can listen");
let address = listener
.local_addr()
.expect("a bound socket has an address");
let socket = bound(loopback());
socket
.connect(&address)
.expect("a loopback listener with room takes a connection");
Self {
socket,
_listener: listener,
}
}
fn address(&self) -> SocketAddr {
self.socket
.local_addr()
.expect("a bound socket has an address")
.as_socket()
.expect("a TCP socket has an IP address")
}
}
#[cfg(all(feature = "tcp", any(target_os = "linux", target_os = "android")))]
fn listener_with_room_for_one() -> (Socket, SocketAddr) {
let socket = bound(loopback());
socket.listen(0).expect("a bound socket can listen");
let address = socket
.local_addr()
.expect("a bound socket has an address")
.as_socket()
.expect("a TCP socket has an IP address");
(socket, address)
}
#[cfg(any(feature = "tcp", feature = "udp"))]
fn loopback() -> SocketAddr {
SocketAddr::from((Ipv4Addr::LOCALHOST, 0))
}
#[cfg(feature = "tcp")]
fn bound(address: SocketAddr) -> Socket {
let socket = Socket::new(Domain::for_address(address), Type::STREAM, None)
.expect("a TCP socket can be made");
socket
.bind(&SockAddr::from(address))
.expect("a loopback port can be bound");
socket
}