mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-04-22 16:17:23 +08:00
fix: listener parsing (#2143)
EasyTier Core / pre_job (push) Waiting to run
EasyTier Core / build_web (push) Blocked by required conditions
EasyTier Core / build (freebsd-13.2-x86_64, 13.2, ubuntu-24.04, x86_64-unknown-freebsd) (push) Blocked by required conditions
EasyTier Core / build (linux-aarch64, ubuntu-24.04-arm, aarch64-unknown-linux-musl) (push) Blocked by required conditions
EasyTier Core / build (linux-arm, ubuntu-24.04, arm-unknown-linux-musleabi) (push) Blocked by required conditions
EasyTier Core / build (linux-armhf, ubuntu-24.04, arm-unknown-linux-musleabihf) (push) Blocked by required conditions
EasyTier Core / build (linux-armv7, ubuntu-24.04, armv7-unknown-linux-musleabi) (push) Blocked by required conditions
EasyTier Core / build (linux-armv7hf, ubuntu-24.04, armv7-unknown-linux-musleabihf) (push) Blocked by required conditions
EasyTier Core / build (linux-loongarch64, ubuntu-24.04, loongarch64-unknown-linux-musl) (push) Blocked by required conditions
EasyTier Core / build (linux-mips, ubuntu-24.04, mips-unknown-linux-musl) (push) Blocked by required conditions
EasyTier Core / build (linux-mipsel, ubuntu-24.04, mipsel-unknown-linux-musl) (push) Blocked by required conditions
EasyTier Core / build (linux-riscv64, ubuntu-24.04, riscv64gc-unknown-linux-musl) (push) Blocked by required conditions
EasyTier Core / build (linux-x86_64, ubuntu-24.04, x86_64-unknown-linux-musl) (push) Blocked by required conditions
EasyTier Core / build (macos-aarch64, macos-latest, aarch64-apple-darwin) (push) Blocked by required conditions
EasyTier Core / build (macos-x86_64, macos-latest, x86_64-apple-darwin) (push) Blocked by required conditions
EasyTier Core / build (windows-arm64, windows-11-arm, aarch64-pc-windows-msvc) (push) Blocked by required conditions
EasyTier Core / build (windows-i686, windows-latest, i686-pc-windows-msvc) (push) Blocked by required conditions
EasyTier Core / build (windows-x86_64, windows-latest, x86_64-pc-windows-msvc) (push) Blocked by required conditions
EasyTier Core / build_magisk (push) Blocked by required conditions
EasyTier Core / core-result (push) Blocked by required conditions
EasyTier GUI / pre_job (push) Waiting to run
EasyTier GUI / build-gui (linux-aarch64, aarch64-unknown-linux-gnu, ubuntu-24.04-arm, aarch64-unknown-linux-musl) (push) Blocked by required conditions
EasyTier GUI / build-gui (linux-x86_64, x86_64-unknown-linux-gnu, ubuntu-24.04, x86_64-unknown-linux-musl) (push) Blocked by required conditions
EasyTier GUI / build-gui (macos-aarch64, aarch64-apple-darwin, macos-latest, aarch64-apple-darwin) (push) Blocked by required conditions
EasyTier GUI / build-gui (macos-x86_64, x86_64-apple-darwin, macos-latest, x86_64-apple-darwin) (push) Blocked by required conditions
EasyTier GUI / build-gui (windows-arm64, aarch64-pc-windows-msvc, windows-11-arm, aarch64-pc-windows-msvc) (push) Blocked by required conditions
EasyTier GUI / build-gui (windows-i686, i686-pc-windows-msvc, windows-latest, i686-pc-windows-msvc) (push) Blocked by required conditions
EasyTier GUI / build-gui (windows-x86_64, x86_64-pc-windows-msvc, windows-latest, x86_64-pc-windows-msvc) (push) Blocked by required conditions
EasyTier GUI / gui-result (push) Blocked by required conditions
EasyTier Mobile / pre_job (push) Waiting to run
EasyTier Mobile / build-mobile (aarch64, aarch64-linux-android) (push) Blocked by required conditions
EasyTier Mobile / build-mobile (armv7, armv7-linux-androideabi) (push) Blocked by required conditions
EasyTier Mobile / build-mobile (i686, i686-linux-android) (push) Blocked by required conditions
EasyTier Mobile / build-mobile (x86_64, x86_64-linux-android) (push) Blocked by required conditions
EasyTier Mobile / mobile-result (push) Blocked by required conditions
Nix Check / check-full-shell (push) Waiting to run
EasyTier OHOS / cargo_fmt_check (push) Waiting to run
EasyTier OHOS / pre_job (push) Waiting to run
EasyTier OHOS / build-ohos (push) Blocked by required conditions
EasyTier Test / pre_job (push) Waiting to run
EasyTier Test / Run linters & check (push) Blocked by required conditions
EasyTier Test / Build test (push) Blocked by required conditions
EasyTier Test / Test (easytier) (push) Blocked by required conditions
EasyTier Test / Test (three_node) (push) Blocked by required conditions
EasyTier Test / Test (three_node::subnet_proxy_three_node_test) (push) Blocked by required conditions
EasyTier Test / test (push) Blocked by required conditions
EasyTier Core / pre_job (push) Waiting to run
EasyTier Core / build_web (push) Blocked by required conditions
EasyTier Core / build (freebsd-13.2-x86_64, 13.2, ubuntu-24.04, x86_64-unknown-freebsd) (push) Blocked by required conditions
EasyTier Core / build (linux-aarch64, ubuntu-24.04-arm, aarch64-unknown-linux-musl) (push) Blocked by required conditions
EasyTier Core / build (linux-arm, ubuntu-24.04, arm-unknown-linux-musleabi) (push) Blocked by required conditions
EasyTier Core / build (linux-armhf, ubuntu-24.04, arm-unknown-linux-musleabihf) (push) Blocked by required conditions
EasyTier Core / build (linux-armv7, ubuntu-24.04, armv7-unknown-linux-musleabi) (push) Blocked by required conditions
EasyTier Core / build (linux-armv7hf, ubuntu-24.04, armv7-unknown-linux-musleabihf) (push) Blocked by required conditions
EasyTier Core / build (linux-loongarch64, ubuntu-24.04, loongarch64-unknown-linux-musl) (push) Blocked by required conditions
EasyTier Core / build (linux-mips, ubuntu-24.04, mips-unknown-linux-musl) (push) Blocked by required conditions
EasyTier Core / build (linux-mipsel, ubuntu-24.04, mipsel-unknown-linux-musl) (push) Blocked by required conditions
EasyTier Core / build (linux-riscv64, ubuntu-24.04, riscv64gc-unknown-linux-musl) (push) Blocked by required conditions
EasyTier Core / build (linux-x86_64, ubuntu-24.04, x86_64-unknown-linux-musl) (push) Blocked by required conditions
EasyTier Core / build (macos-aarch64, macos-latest, aarch64-apple-darwin) (push) Blocked by required conditions
EasyTier Core / build (macos-x86_64, macos-latest, x86_64-apple-darwin) (push) Blocked by required conditions
EasyTier Core / build (windows-arm64, windows-11-arm, aarch64-pc-windows-msvc) (push) Blocked by required conditions
EasyTier Core / build (windows-i686, windows-latest, i686-pc-windows-msvc) (push) Blocked by required conditions
EasyTier Core / build (windows-x86_64, windows-latest, x86_64-pc-windows-msvc) (push) Blocked by required conditions
EasyTier Core / build_magisk (push) Blocked by required conditions
EasyTier Core / core-result (push) Blocked by required conditions
EasyTier GUI / pre_job (push) Waiting to run
EasyTier GUI / build-gui (linux-aarch64, aarch64-unknown-linux-gnu, ubuntu-24.04-arm, aarch64-unknown-linux-musl) (push) Blocked by required conditions
EasyTier GUI / build-gui (linux-x86_64, x86_64-unknown-linux-gnu, ubuntu-24.04, x86_64-unknown-linux-musl) (push) Blocked by required conditions
EasyTier GUI / build-gui (macos-aarch64, aarch64-apple-darwin, macos-latest, aarch64-apple-darwin) (push) Blocked by required conditions
EasyTier GUI / build-gui (macos-x86_64, x86_64-apple-darwin, macos-latest, x86_64-apple-darwin) (push) Blocked by required conditions
EasyTier GUI / build-gui (windows-arm64, aarch64-pc-windows-msvc, windows-11-arm, aarch64-pc-windows-msvc) (push) Blocked by required conditions
EasyTier GUI / build-gui (windows-i686, i686-pc-windows-msvc, windows-latest, i686-pc-windows-msvc) (push) Blocked by required conditions
EasyTier GUI / build-gui (windows-x86_64, x86_64-pc-windows-msvc, windows-latest, x86_64-pc-windows-msvc) (push) Blocked by required conditions
EasyTier GUI / gui-result (push) Blocked by required conditions
EasyTier Mobile / pre_job (push) Waiting to run
EasyTier Mobile / build-mobile (aarch64, aarch64-linux-android) (push) Blocked by required conditions
EasyTier Mobile / build-mobile (armv7, armv7-linux-androideabi) (push) Blocked by required conditions
EasyTier Mobile / build-mobile (i686, i686-linux-android) (push) Blocked by required conditions
EasyTier Mobile / build-mobile (x86_64, x86_64-linux-android) (push) Blocked by required conditions
EasyTier Mobile / mobile-result (push) Blocked by required conditions
Nix Check / check-full-shell (push) Waiting to run
EasyTier OHOS / cargo_fmt_check (push) Waiting to run
EasyTier OHOS / pre_job (push) Waiting to run
EasyTier OHOS / build-ohos (push) Blocked by required conditions
EasyTier Test / pre_job (push) Waiting to run
EasyTier Test / Run linters & check (push) Blocked by required conditions
EasyTier Test / Build test (push) Blocked by required conditions
EasyTier Test / Test (easytier) (push) Blocked by required conditions
EasyTier Test / Test (three_node) (push) Blocked by required conditions
EasyTier Test / Test (three_node::subnet_proxy_three_node_test) (push) Blocked by required conditions
EasyTier Test / test (push) Blocked by required conditions
Fixes a CLI listener parsing regression where url crate special-casing for ws/wss could misinterpret inputs like ws:11011, and adds coverage to prevent future regressions. Changes: Refactors listener parsing to avoid url::Url parsing for proto:port forms and to support additional shorthand inputs (port-only / IP-only / SocketAddr). Centralizes “expand to all IpScheme variants” logic in a helper (gen_listeners) while preserving the “port=0 is dynamic” behavior. Adds unit tests covering valid/invalid listener inputs and expansion behavior.
This commit is contained in:
+150
-49
@@ -1,12 +1,5 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::{
|
||||
net::{IpAddr, SocketAddr},
|
||||
path::PathBuf,
|
||||
process::ExitCode,
|
||||
sync::{Arc, atomic::AtomicBool},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
ShellType,
|
||||
common::{
|
||||
@@ -30,6 +23,12 @@ use anyhow::Context;
|
||||
use cidr::IpCidr;
|
||||
use clap::{CommandFactory, Parser};
|
||||
use rust_i18n::t;
|
||||
use std::{
|
||||
net::{IpAddr, SocketAddr},
|
||||
path::PathBuf,
|
||||
process::ExitCode,
|
||||
sync::{Arc, atomic::AtomicBool},
|
||||
};
|
||||
use strum::VariantArray;
|
||||
use tokio::io::AsyncReadExt;
|
||||
|
||||
@@ -744,55 +743,69 @@ struct RpcPortalOptions {
|
||||
}
|
||||
|
||||
impl Cli {
|
||||
fn gen_listeners(addr: SocketAddr) -> impl Iterator<Item = String> {
|
||||
let dynamic = addr.port() == 0;
|
||||
IpScheme::VARIANTS.iter().map(move |proto| {
|
||||
let mut addr = addr;
|
||||
if !dynamic {
|
||||
addr.set_port(addr.port() + proto.port_offset());
|
||||
}
|
||||
format!("{}://{}", proto, addr)
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_listeners(no_listener: bool, listeners: Vec<String>) -> anyhow::Result<Vec<String>> {
|
||||
if no_listener || listeners.is_empty() {
|
||||
return Ok(vec![]);
|
||||
}
|
||||
|
||||
if listeners.len() == 1
|
||||
&& let Ok(port) = listeners[0].parse::<u16>()
|
||||
{
|
||||
let listeners = IpScheme::VARIANTS
|
||||
.iter()
|
||||
.map(|proto| {
|
||||
format!(
|
||||
"{}://0.0.0.0:{}",
|
||||
proto,
|
||||
if port == 0 {
|
||||
0
|
||||
} else {
|
||||
port + proto.port_offset()
|
||||
}
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
return Ok(listeners);
|
||||
let mut parsed = vec![];
|
||||
|
||||
for l in listeners.into_iter() {
|
||||
if let Ok(port) = l.parse::<u16>() {
|
||||
parsed.extend(Self::gen_listeners(SocketAddr::new(
|
||||
"0.0.0.0".parse()?,
|
||||
port,
|
||||
)));
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Ok(ip) = l.trim_matches(|c| c == '[' || c == ']').parse::<IpAddr>() {
|
||||
parsed.extend(Self::gen_listeners(SocketAddr::new(ip, 11010)));
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Ok(addr) = l.parse::<SocketAddr>() {
|
||||
parsed.extend(Self::gen_listeners(addr));
|
||||
continue;
|
||||
}
|
||||
|
||||
let (scheme, rest) = l.split_once(':').unwrap_or((&l, ""));
|
||||
let Ok(scheme) = scheme.parse::<IpScheme>() else {
|
||||
anyhow::bail!("invalid listener: {}", l);
|
||||
};
|
||||
|
||||
if rest.is_empty() {
|
||||
parsed.push(format!(
|
||||
"{}://0.0.0.0:{}",
|
||||
scheme,
|
||||
11010 + scheme.port_offset()
|
||||
));
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Ok(port) = rest.parse::<u16>() {
|
||||
parsed.push(format!("{}://0.0.0.0:{}", scheme, port));
|
||||
continue;
|
||||
}
|
||||
|
||||
if !l.parse::<url::Url>()?.has_authority() {
|
||||
anyhow::bail!("invalid listener: {}", l);
|
||||
}
|
||||
parsed.push(l);
|
||||
}
|
||||
|
||||
listeners
|
||||
.into_iter()
|
||||
.map(|l| {
|
||||
let l = l
|
||||
.parse::<url::Url>()
|
||||
.or_else(|_| url::Url::parse(&format!("{}:", l)))?;
|
||||
|
||||
if l.has_authority() {
|
||||
return Ok(l.to_string());
|
||||
}
|
||||
|
||||
let scheme: IpScheme = l.scheme().parse()?;
|
||||
let port = {
|
||||
let port = l.path();
|
||||
if port.is_empty() {
|
||||
11010 + scheme.port_offset()
|
||||
} else {
|
||||
port.parse::<u16>()
|
||||
.with_context(|| format!("invalid port: {}", port))?
|
||||
}
|
||||
};
|
||||
Ok(format!("{}://0.0.0.0:{}", scheme, port))
|
||||
})
|
||||
.collect()
|
||||
Ok(parsed)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1594,3 +1607,91 @@ async fn validate_config(cli: &Cli) -> anyhow::Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_parse_listeners() {
|
||||
type IpSchemeMap = fn(&IpScheme) -> String;
|
||||
|
||||
let cases: [(&str, IpSchemeMap); _] = [
|
||||
("0", |s| format!("{}://0.0.0.0:0", s)),
|
||||
("11010", |s| {
|
||||
format!("{}://0.0.0.0:{}", s, 11010 + s.port_offset())
|
||||
}),
|
||||
("1.1.1.1", |s| {
|
||||
format!("{}://1.1.1.1:{}", s, 11010 + s.port_offset())
|
||||
}),
|
||||
("1.1.1.1:50000", |s| {
|
||||
format!("{}://1.1.1.1:{}", s, 50000 + s.port_offset())
|
||||
}),
|
||||
("[::1]", |s| {
|
||||
format!("{}://[::1]:{}", s, 11010 + s.port_offset())
|
||||
}),
|
||||
("[::1]:50000", |s| {
|
||||
format!("{}://[::1]:{}", s, 50000 + s.port_offset())
|
||||
}),
|
||||
];
|
||||
|
||||
for (input, output) in cases {
|
||||
assert_eq!(
|
||||
Cli::parse_listeners(false, vec![input.to_string()]).unwrap(),
|
||||
IpScheme::VARIANTS.iter().map(output).collect::<Vec<_>>()
|
||||
);
|
||||
}
|
||||
|
||||
let input = cases.iter().map(|(i, _)| i.to_string()).collect::<Vec<_>>();
|
||||
let output = cases
|
||||
.iter()
|
||||
.flat_map(|(_, o)| IpScheme::VARIANTS.iter().map(o))
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(Cli::parse_listeners(false, input).unwrap(), output);
|
||||
|
||||
let cases: [(IpSchemeMap, IpSchemeMap); _] = [
|
||||
(
|
||||
|s| format!("{}", s),
|
||||
|s| format!("{}://0.0.0.0:{}", s, 11010 + s.port_offset()),
|
||||
),
|
||||
(
|
||||
|s| format!("{}:50000", s),
|
||||
|s| format!("{}://0.0.0.0:50000", s),
|
||||
),
|
||||
(
|
||||
|s| format!("{}://1.1.1.1:50000", s),
|
||||
|s| format!("{}://1.1.1.1:50000", s),
|
||||
),
|
||||
];
|
||||
|
||||
for (input, output) in cases {
|
||||
assert_eq!(
|
||||
Cli::parse_listeners(
|
||||
false,
|
||||
IpScheme::VARIANTS.iter().map(input).collect::<Vec<_>>(),
|
||||
)
|
||||
.unwrap(),
|
||||
IpScheme::VARIANTS.iter().map(output).collect::<Vec<_>>()
|
||||
);
|
||||
}
|
||||
|
||||
let input = cases
|
||||
.iter()
|
||||
.flat_map(|(i, _)| IpScheme::VARIANTS.iter().map(i))
|
||||
.collect::<Vec<_>>();
|
||||
let output = cases
|
||||
.iter()
|
||||
.flat_map(|(_, o)| IpScheme::VARIANTS.iter().map(o))
|
||||
.collect::<Vec<_>>();
|
||||
assert_eq!(Cli::parse_listeners(false, input).unwrap(), output);
|
||||
|
||||
let cases = ["tcp://[::1", "xxx", "tcp:/abc", "tcp:abc"];
|
||||
for input in cases {
|
||||
assert!(
|
||||
Cli::parse_listeners(false, vec![input.to_string()]).is_err(),
|
||||
"input: {}",
|
||||
input
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user