Skip to content

Commit

Permalink
feat: allow controlling the address type for binding
Browse files Browse the repository at this point in the history
Closes: #1
  • Loading branch information
ctron committed Dec 5, 2024
1 parent de3b822 commit dc57267
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 16 deletions.
26 changes: 24 additions & 2 deletions src/cmd/create/public.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{
cmd::create::CreateCommon,
config::{Client, ClientType, Config},
http::{create_client, HttpOptions},
server::Server,
server::{Bind, Server},
utils::OrNone,
};
use anyhow::bail;
Expand Down Expand Up @@ -30,6 +30,18 @@ pub struct CreatePublic {
#[arg(short, long)]
pub open: bool,

/// Choose how to bind the local server
#[arg(short, long, env = "BIND_MODE", value_enum, default_value_t = Bind::Prefer6)]
pub bind: Bind,

/// Use IPv4 only binding (equivalent to --bind only4)
#[arg(short = '4', conflicts_with_all = ["bind", "only6"])]
pub only4: bool,

/// Use IPv6 only binding (equivalent to --bind only6)
#[arg(short = '6', conflicts_with = "bind")]
pub only6: bool,

#[command(flatten)]
pub http: HttpOptions,
}
Expand All @@ -47,7 +59,7 @@ impl CreatePublic {
);
}

let server = Server::new(self.port).await?;
let server = Server::new(self.bind_mode(), self.port).await?;
let redirect = format!("http://localhost:{}", server.port);

let client = create_client(&self.http).await?;
Expand Down Expand Up @@ -105,4 +117,14 @@ Open the following URL in your browser and perform the interactive login process

Ok(())
}

fn bind_mode(&self) -> Bind {
if self.only4 {
Bind::Only4
} else if self.only6 {
Bind::Only6
} else {
self.bind
}
}
}
64 changes: 50 additions & 14 deletions src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,54 @@ use tokio::{
sync::{oneshot, Mutex},
};

#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, clap::ValueEnum)]
pub enum Bind {
/// Try IPv6 first, then fall back to IPv4
#[default]
Prefer6,
/// Try IPv4 first, then fall back to IPv6
Prefer4,
/// Only try IPv6
Only6,
/// Only try IPv4
Only4,
}

impl Bind {
pub async fn into_acceptor(self, port: u16) -> anyhow::Result<TcpListener> {
Ok(match self {
Self::Prefer6 => match TcpListener::bind((Ipv6Addr::LOCALHOST, port)).await {
Ok(acceptor) => acceptor,
Err(err) => {
log::info!("Failed to bind to IPv6 localhost, trying IPv4 instead: {err}");
match TcpListener::bind((Ipv4Addr::LOCALHOST, port)).await {
Ok(acceptor) => acceptor,
Err(err) => {
log::error!("Failed to bind to either IPv6 or IPv4: {err}");
bail!("Unable to bind to IPv4 or IPv6: {err}");
}
}
}
},
Self::Prefer4 => match TcpListener::bind((Ipv4Addr::LOCALHOST, port)).await {
Ok(acceptor) => acceptor,
Err(err) => {
log::info!("Failed to bind to IPv4 localhost, trying IPv6 instead: {err}");
match TcpListener::bind((Ipv6Addr::LOCALHOST, port)).await {
Ok(acceptor) => acceptor,
Err(err) => {
log::error!("Failed to bind to either IPv6 or IPv4: {err}");
bail!("Unable to bind to IPv4 or IPv6: {err}");
}
}
}
},
Self::Only6 => TcpListener::bind((Ipv6Addr::LOCALHOST, port)).await?,
Self::Only4 => TcpListener::bind((Ipv4Addr::LOCALHOST, port)).await?,
})
}
}

pub struct FlowResult {
pub code: String,
}
Expand Down Expand Up @@ -48,24 +96,12 @@ async fn receive(
}

impl Server {
pub async fn new(port: Option<u16>) -> anyhow::Result<Self> {
pub async fn new(bind: Bind, port: Option<u16>) -> anyhow::Result<Self> {
let (tx, rx) = oneshot::channel();

let port = port.unwrap_or_default();

let acceptor = match TcpListener::bind((Ipv6Addr::LOCALHOST, port)).await {
Ok(acceptor) => acceptor,
Err(err) => {
log::info!("Failed to bind to IPv6 localhost, trying IPv4 instead: {err}");
match TcpListener::bind((Ipv4Addr::LOCALHOST, port)).await {
Ok(acceptor) => acceptor,
Err(err) => {
log::error!("Failed to bind to either IPv6 or IPv4: {err}");
bail!("Unable to bind to IPv4 or IPv6: {err}");
}
}
}
};
let acceptor = bind.into_acceptor(port).await?;
let acceptor = acceptor.into_std()?;

let port = acceptor.local_addr()?.port();
Expand Down

0 comments on commit dc57267

Please sign in to comment.