trillium_async_std/
client.rs1use crate::{AsyncStdRuntime, AsyncStdTransport};
2use async_std::net::{TcpStream, ToSocketAddrs};
3use std::{
4 io::{Error, ErrorKind, Result},
5 net::SocketAddr,
6};
7use trillium_server_common::{Connector, Destination, Transport, url::Url};
8
9#[derive(Default, Debug, Clone, Copy)]
11pub struct ClientConfig {
12 pub nodelay: Option<bool>,
14
15 pub ttl: Option<u32>,
17}
18
19impl ClientConfig {
20 pub const fn new() -> Self {
22 Self {
23 nodelay: None,
24 ttl: None,
25 }
26 }
27
28 pub const fn with_nodelay(mut self, nodelay: bool) -> Self {
30 self.nodelay = Some(nodelay);
31 self
32 }
33
34 pub const fn with_ttl(mut self, ttl: u32) -> Self {
36 self.ttl = Some(ttl);
37 self
38 }
39}
40
41impl Connector for ClientConfig {
42 type Runtime = AsyncStdRuntime;
43 type Transport = AsyncStdTransport<TcpStream>;
44 type Udp = crate::AsyncStdUdpSocket;
45
46 async fn connect(&self, url: &Url) -> Result<Self::Transport> {
47 self.connect_to(Destination::from_url(url)?).await
48 }
49
50 async fn connect_to(&self, destination: Destination) -> Result<Self::Transport> {
51 if destination.secure() {
52 return Err(Error::new(
53 ErrorKind::InvalidInput,
54 "this connector does not support TLS",
55 ));
56 }
57
58 let addrs = destination.addrs();
59 let mut tcp = if addrs.is_empty() {
60 let host = destination.host().ok_or_else(|| {
61 Error::new(
62 ErrorKind::InvalidInput,
63 "destination has neither host nor addresses",
64 )
65 })?;
66 Self::Transport::connect((host, destination.port())).await?
67 } else {
68 Self::Transport::connect(addrs).await?
69 };
70
71 if let Some(nodelay) = self.nodelay {
72 tcp.set_nodelay(nodelay)?;
73 }
74
75 if let Some(ttl) = self.ttl {
76 tcp.set_ip_ttl(ttl)?;
77 }
78
79 Ok(tcp)
80 }
81
82 fn runtime(&self) -> Self::Runtime {
83 AsyncStdRuntime::default()
84 }
85
86 async fn resolve(&self, host: &str, port: u16) -> Result<Vec<SocketAddr>> {
87 (host, port).to_socket_addrs().await.map(Iterator::collect)
88 }
89}