use crate::{
either::Either,
event, msg,
path::secret,
stream::{
application::Stream,
endpoint,
environment::tokio::{self as env, Environment},
recv,
socket::Protocol,
},
};
use std::{io, net::SocketAddr, time::Duration};
use tokio::net::TcpStream;
#[inline]
pub async fn connect_udp<H, Sub>(
handshake: H,
acceptor_addr: SocketAddr,
env: &Environment<Sub>,
) -> io::Result<Stream<Sub>>
where
H: core::future::Future<Output = io::Result<secret::map::Peer>>,
Sub: event::Subscriber + Clone,
{
let entry = handshake.await?;
let stream = if env.has_recv_pool() {
let peer = env::udp::Pooled(acceptor_addr.into());
endpoint::open_stream(env, entry, peer, None)?
} else {
let peer = env::udp::Owned(acceptor_addr.into(), recv_buffer());
endpoint::open_stream(env, entry, peer, None)?
};
let stream = stream.connect()?;
debug_assert_eq!(stream.protocol(), Protocol::Udp);
Ok(stream)
}
#[inline]
pub async fn connect_tcp<H, Sub>(
handshake: H,
acceptor_addr: SocketAddr,
env: &Environment<Sub>,
linger: Option<Duration>,
) -> io::Result<Stream<Sub>>
where
H: core::future::Future<Output = io::Result<secret::map::Peer>>,
Sub: event::Subscriber + Clone,
{
let (socket, entry) = tokio::try_join!(TcpStream::connect(acceptor_addr), handshake,)?;
let _ = socket.set_nodelay(true);
if linger.is_some() {
let _ = socket.set_linger(linger);
}
let peer_addr = if acceptor_addr.ip().is_unspecified() {
socket.peer_addr()?
} else {
acceptor_addr
}
.into();
let local_port = socket.local_addr()?.port();
let peer = env::tcp::Registered {
socket,
peer_addr,
local_port,
recv_buffer: recv_buffer(),
};
let stream = endpoint::open_stream(env, entry, peer, None)?;
let stream = stream.connect()?;
debug_assert_eq!(stream.protocol(), Protocol::Tcp);
Ok(stream)
}
#[inline]
pub async fn connect_tcp_with<Sub>(
entry: secret::map::Peer,
socket: TcpStream,
env: &Environment<Sub>,
) -> io::Result<Stream<Sub>>
where
Sub: event::Subscriber + Clone,
{
let local_port = socket.local_addr()?.port();
let peer_addr = socket.peer_addr()?.into();
let peer = env::tcp::Registered {
socket,
peer_addr,
local_port,
recv_buffer: recv_buffer(),
};
let stream = endpoint::open_stream(env, entry, peer, None)?;
let stream = stream.connect()?;
debug_assert_eq!(stream.protocol(), Protocol::Tcp);
Ok(stream)
}
#[inline]
fn recv_buffer() -> recv::shared::RecvBuffer {
let recv_buffer = recv::buffer::Local::new(msg::recv::Message::new(9000), None);
Either::A(recv_buffer)
}