Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added wrapper type and todos #348

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions rama-net/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub mod client;
pub mod forwarded;
pub mod stream;
pub mod user;
pub mod mode;

pub(crate) mod proto;
#[doc(inline)]
Expand Down
31 changes: 31 additions & 0 deletions rama-net/src/mode.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
/// Enum representing the IP modes that can be used by the DNS resolver.
pub enum DnsResolveIpMode {
#[default]
Dual,
SingleIpV4,
SingleIpV6,
DualPreferIpV4
}

impl DnsResolveIpMode{

/// checks if IPv4 is supported in current mode
pub fn ipv4_supported(&self) -> bool {
matches!(self.mode, DnsResolveIpMode::Dual | DnsResolveIpMode::SingleIpV4 | DnsResolveIpMode::DualPreferIpV4)
}

/// checks if IPv6 is supported in current mode
pub fn ipv6_supported(&self) -> bool {
matches!(self.mode, DnsResolveIpMode::Dual | DnsResolveIpMode::SingleIpV6)
}
}

///Mode for establishing a connection
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum ConnectIpMode {
#[default]
Dual,
Ipv4,
Ipv6,
}
97 changes: 54 additions & 43 deletions rama-tcp/src/client/connect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use tokio::{
Semaphore,
},
};
use rama_net::mode::{ConnectIpMode, DnsResolveIpMode};

/// Trait used internally by [`tcp_connect`] and the `TcpConnector`
/// to actually establish the [`TcpStream`.]
Expand Down Expand Up @@ -154,8 +155,8 @@ async fn tcp_connect_inner<State, Dns, Connector>(
ctx: &Context<State>,
domain: Domain,
port: u16,
dns: Dns,
connector: Connector,
dns: DnsResolveIpMode,
connector: ConnectIpMode<Connector>,
) -> Result<(TcpStream, SocketAddr), OpaqueError>
where
State: Clone + Send + Sync + 'static,
Expand All @@ -167,37 +168,32 @@ where
let connected = Arc::new(AtomicBool::new(false));
let sem = Arc::new(Semaphore::new(3));

// IPv6
let ipv6_tx = tx.clone();
let ipv6_domain = domain.clone();
let ipv6_connected = connected.clone();
let ipv6_sem = sem.clone();
ctx.spawn(tcp_connect_inner_branch(
dns.clone(),
connector.clone(),
IpKind::Ipv6,
ipv6_domain,
port,
ipv6_tx,
ipv6_connected,
ipv6_sem,
));
if dns.ipv4_supported() {
ctx.spawn(tcp_connect_inner_branch(
dns.clone(),
connector.clone(),
IpKind::Ipv4,
domain.clone(),
port,
tx.clone(),
connected.clone(),
sem.clone(),
));
}


// IPv4
let ipv4_tx = tx;
let ipv4_domain = domain.clone();
let ipv4_connected = connected.clone();
let ipv4_sem = sem;
ctx.spawn(tcp_connect_inner_branch(
dns,
connector,
IpKind::Ipv4,
ipv4_domain,
port,
ipv4_tx,
ipv4_connected,
ipv4_sem,
));
if dns.ipv6_supported() {
ctx.spawn(tcp_connect_inner_branch(
dns.clone(),
connector.clone(),
IpKind::Ipv6,
domain.clone(),
port,
tx.clone(),
connected.clone(),
sem.clone(),
));
}

// wait for the first connection to succeed,
// ignore the rest of the connections (sorry, but not sorry)
Expand All @@ -219,7 +215,7 @@ enum IpKind {

#[allow(clippy::too_many_arguments)]
async fn tcp_connect_inner_branch<Dns, Connector>(
dns: Dns,
dns: DnsResolveIpMode,
connector: Connector,
ip_kind: IpKind,
domain: Domain,
Expand All @@ -231,23 +227,38 @@ async fn tcp_connect_inner_branch<Dns, Connector>(
Dns: DnsResolver<Error: Into<BoxError>> + Clone,
Connector: TcpStreamConnector<Error: Into<BoxError> + Send + 'static> + Clone,
{

let ip_it = match ip_kind {
IpKind::Ipv4 => match dns.ipv4_lookup(domain).await {
Ok(ips) => Either::A(ips.into_iter().map(IpAddr::V4)),
Err(err) => {
let err = OpaqueError::from_boxed(err.into());
tracing::trace!(err = %err, "[{ip_kind:?}] failed to resolve domain to IPv4 addresses");
return;
}
},
IpKind::Ipv6 => match dns.ipv6_lookup(domain).await {
IpKind::Ipv4 =>{
if dns.ipv4_supported(){
match dns.ipv4_lookup(domain).await {
Ok(ips) => Either::A(ips.into_iter().map(IpAddr::V4)),
Err(err) => {
let err = OpaqueError::from_boxed(err.into());
tracing::trace!(err = %err, "[{ip_kind:?}] failed to resolve domain to IPv4 addresses");
return;
}
}

} else {
tracing::debug!("IPv4 not supported by the DNS mode: no connection can be established");
}
},
IpKind::Ipv6 => {
if dns.ipv6_supported() {
match dns.ipv6_lookup(domain).await {
Ok(ips) => Either::B(ips.into_iter().map(IpAddr::V6)),
Err(err) => {
let err = OpaqueError::from_boxed(err.into());
tracing::trace!(err = ?err, "[{ip_kind:?}] failed to resolve domain to IPv6 addresses");
return;
}
},
}
}
else {
tracing::debug!("IPv4 not supported by the DNS mode: no connection can be established");
}
}
};

for (index, ip) in ip_it.enumerate() {
Expand Down