server: prompt for listen port before endpoint

also fix a logic bug if user cancels port selection in client
when trying to override endpoint.

fixes #148
pull/153/head
Jake McGinty 2021-09-15 20:43:38 +09:00
parent 4fa689d400
commit cacd80b283
3 changed files with 54 additions and 42 deletions

View File

@ -839,10 +839,11 @@ fn set_listen_port(
interface: &InterfaceName, interface: &InterfaceName,
unset: bool, unset: bool,
network: NetworkOpt, network: NetworkOpt,
) -> Result<(), Error> { ) -> Result<Option<u16>, Error> {
let mut config = InterfaceConfig::from_interface(interface)?; let mut config = InterfaceConfig::from_interface(interface)?;
if let Some(listen_port) = prompts::set_listen_port(&config.interface, unset)? { let listen_port = prompts::set_listen_port(&config.interface, unset)?;
if let Some(listen_port) = listen_port {
wg::set_listen_port(interface, listen_port, network.backend)?; wg::set_listen_port(interface, listen_port, network.backend)?;
log::info!("the interface is updated"); log::info!("the interface is updated");
@ -853,7 +854,7 @@ fn set_listen_port(
log::info!("exiting without updating the listen port."); log::info!("exiting without updating the listen port.");
} }
Ok(()) Ok(listen_port.flatten())
} }
fn override_endpoint( fn override_endpoint(
@ -862,20 +863,32 @@ fn override_endpoint(
network: NetworkOpt, network: NetworkOpt,
) -> Result<(), Error> { ) -> Result<(), Error> {
let config = InterfaceConfig::from_interface(interface)?; let config = InterfaceConfig::from_interface(interface)?;
if !unset && config.interface.listen_port.is_none() { let endpoint_contents = if unset {
prompts::unset_override_endpoint()?.then(|| EndpointContents::Unset)
} else {
let listen_port = if let Some(listen_port) = config.interface.listen_port {
Some(listen_port)
} else {
println!( println!(
"{}: you need to set a listen port for your interface first.", "{}: you need to set a listen port for your interface first.",
"note".bold().yellow() "note".bold().yellow()
); );
set_listen_port(interface, unset, network)?; set_listen_port(interface, unset, network)?
} };
let endpoint = if let Some(port) = listen_port {
prompts::override_endpoint(port)?
} else {
None
};
endpoint.map(|endpoint| EndpointContents::Set(endpoint))
};
if let Some(endpoint) = prompts::override_endpoint(unset)? { if let Some(contents) = endpoint_contents {
log::info!("Updating endpoint."); log::info!("Updating endpoint.");
Api::new(&config.server).http_form( Api::new(&config.server).http_form(
"PUT", "PUT",
"/user/endpoint", "/user/endpoint",
EndpointContents::from(endpoint), contents,
)?; )?;
} else { } else {
log::info!("exiting without overriding endpoint."); log::info!("exiting without overriding endpoint.");
@ -1119,10 +1132,10 @@ fn run(opt: Opts) -> Result<(), Error> {
Command::DeleteAssociation { interface } => delete_association(&interface)?, Command::DeleteAssociation { interface } => delete_association(&interface)?,
Command::ListAssociations { interface } => list_associations(&interface)?, Command::ListAssociations { interface } => list_associations(&interface)?,
Command::SetListenPort { interface, unset } => { Command::SetListenPort { interface, unset } => {
set_listen_port(&interface, unset, opt.network)? set_listen_port(&interface, unset, opt.network)?;
}, },
Command::OverrideEndpoint { interface, unset } => { Command::OverrideEndpoint { interface, unset } => {
override_endpoint(&interface, unset, opt.network)? override_endpoint(&interface, unset, opt.network)?;
}, },
Command::Completions { shell } => { Command::Completions { shell } => {
Opts::clap().gen_completions_to("innernet", shell, &mut std::io::stdout()); Opts::clap().gen_completions_to("innernet", shell, &mut std::io::stdout());

View File

@ -139,16 +139,6 @@ pub fn init_wizard(conf: &ServerConfig, opts: InitializeOpts) -> Result<(), Erro
.interact()? .interact()?
}; };
let endpoint: Endpoint = if let Some(endpoint) = opts.external_endpoint {
endpoint
} else if opts.auto_external_endpoint {
let ip = publicip::get_any(Preference::Ipv4)
.ok_or_else(|| anyhow!("couldn't get external IP"))?;
SocketAddr::new(ip, 51820).into()
} else {
prompts::ask_endpoint()?
};
let listen_port: u16 = if let Some(listen_port) = opts.listen_port { let listen_port: u16 = if let Some(listen_port) = opts.listen_port {
listen_port listen_port
} else { } else {
@ -159,6 +149,18 @@ pub fn init_wizard(conf: &ServerConfig, opts: InitializeOpts) -> Result<(), Erro
.map_err(|_| anyhow!("failed to get listen port."))? .map_err(|_| anyhow!("failed to get listen port."))?
}; };
log::info!("listen port: {}", listen_port);
let endpoint: Endpoint = if let Some(endpoint) = opts.external_endpoint {
endpoint
} else if opts.auto_external_endpoint {
let ip = publicip::get_any(Preference::Ipv4)
.ok_or_else(|| anyhow!("couldn't get external IP"))?;
SocketAddr::new(ip, listen_port).into()
} else {
prompts::ask_endpoint(listen_port)?
};
let our_ip = root_cidr let our_ip = root_cidr
.iter() .iter()
.find(|ip| root_cidr.is_assignable(*ip)) .find(|ip| root_cidr.is_assignable(*ip))

View File

@ -459,7 +459,7 @@ pub fn set_listen_port(
} }
} }
pub fn ask_endpoint() -> Result<Endpoint, Error> { pub fn ask_endpoint(listen_port: u16) -> Result<Endpoint, Error> {
println!("getting external IP address."); println!("getting external IP address.");
let external_ip = if Confirm::with_theme(&*THEME) let external_ip = if Confirm::with_theme(&*THEME)
@ -475,26 +475,23 @@ pub fn ask_endpoint() -> Result<Endpoint, Error> {
Ok(input( Ok(input(
"External endpoint", "External endpoint",
match external_ip { match external_ip {
Some(ip) => Prefill::Editable(SocketAddr::new(ip, 51820).to_string()), Some(ip) => Prefill::Editable(SocketAddr::new(ip, listen_port).to_string()),
None => Prefill::None, None => Prefill::None,
}, },
)?) )?)
} }
pub fn override_endpoint(unset: bool) -> Result<Option<Option<Endpoint>>, Error> { pub fn override_endpoint(listen_port: u16) -> Result<Option<Endpoint>, Error> {
let endpoint = if !unset { Some(ask_endpoint()?) } else { None }; let endpoint = ask_endpoint(listen_port)?;
if confirm(&format!("Set external endpoint to {}?", endpoint))? {
Ok( Ok(Some(endpoint))
if confirm(
&(if let Some(endpoint) = &endpoint {
format!("Set external endpoint to {}?", endpoint)
} else { } else {
"Unset external endpoint to enable automatic endpoint discovery?".to_string() Ok(None)
}), }
)? { }
Some(endpoint)
} else { pub fn unset_override_endpoint() -> Result<bool, Error> {
None Ok(confirm(
}, "Unset external endpoint to enable automatic endpoint discovery?",
) )?)
} }