use crate::{
event,
path::secret,
stream::{
application::Stream,
endpoint,
environment::tokio::{self as env, Environment},
socket::Protocol,
},
};
use std::{io, net::SocketAddr};
use tokio::net::TcpStream;
#[inline]
pub async fn connect_udp<H, Sub>(
handshake: H,
acceptor_addr: SocketAddr,
env: &Environment<Sub>,
subscriber: Sub,
) -> io::Result<Stream<Sub>>
where
H: core::future::Future<Output = io::Result<secret::map::Peer>>,
Sub: event::Subscriber,
{
let peer = handshake.await?;
let stream = endpoint::open_stream(
env,
peer,
env::UdpUnbound(acceptor_addr.into()),
subscriber,
None,
)?;
let mut stream = stream.connect()?;
debug_assert_eq!(stream.protocol(), Protocol::Udp);
write_prelude(&mut stream).await?;
Ok(stream)
}
#[inline]
pub async fn connect_tcp<H, Sub>(
handshake: H,
acceptor_addr: SocketAddr,
env: &Environment<Sub>,
subscriber: Sub,
) -> io::Result<Stream<Sub>>
where
H: core::future::Future<Output = io::Result<secret::map::Peer>>,
Sub: event::Subscriber,
{
let (socket, peer) = tokio::try_join!(TcpStream::connect(acceptor_addr), handshake,)?;
let _ = socket.set_nodelay(true);
let _ = socket.set_linger(Some(core::time::Duration::ZERO));
let peer_addr = if acceptor_addr.ip().is_unspecified() {
socket.peer_addr()?
} else {
acceptor_addr
}
.into();
let local_port = socket.local_addr()?.port();
let stream = endpoint::open_stream(
env,
peer,
env::TcpRegistered {
socket,
peer_addr,
local_port,
},
subscriber,
None,
)?;
let mut stream = stream.connect()?;
debug_assert_eq!(stream.protocol(), Protocol::Tcp);
write_prelude(&mut stream).await?;
Ok(stream)
}
#[inline]
pub async fn connect_tcp_with<Sub>(
peer: secret::map::Peer,
socket: TcpStream,
env: &Environment<Sub>,
subscriber: Sub,
) -> io::Result<Stream<Sub>>
where
Sub: event::Subscriber,
{
let local_port = socket.local_addr()?.port();
let peer_addr = socket.peer_addr()?.into();
let stream = endpoint::open_stream(
env,
peer,
env::TcpRegistered {
socket,
peer_addr,
local_port,
},
subscriber,
None,
)?;
let mut stream = stream.connect()?;
debug_assert_eq!(stream.protocol(), Protocol::Tcp);
write_prelude(&mut stream).await?;
Ok(stream)
}
#[inline]
async fn write_prelude<Sub>(stream: &mut Stream<Sub>) -> io::Result<()>
where
Sub: event::Subscriber,
{
stream
.write_from(&mut s2n_quic_core::buffer::reader::storage::Empty)
.await
.map(|_| ())
}