test(net): e2e-test the UPnP path + add a portmap diagnostic
Address the gap that the port mapper's UPnP path and gateway discovery had no automated coverage (only NAT-PMP did): - UPnP e2e: split map_via_gateway out of discovery and drive it through igd-next against an in-process mock IGD (a std HTTP server returning a canned SOAP envelope). Verifies the real add_port SOAP round-trip and that we request the exact external/internal port + LAN client. - default_gateway parsing is now pure, testable functions with unit tests for the macOS and Linux formats (including the 0.0.0.0 skip). - New 'portmap' CLI subcommand (needs no login): synchronously probes UPnP/NAT-PMP against the real router and reports whether the port was opened + the external address, then removes the test mapping — so a user can verify reachability on their own network. 9 port_mapping tests now cover the NAT-PMP protocol, the UPnP SOAP round-trip, gateway parsing, and the map/renew/cleanup lifecycle.
This commit is contained in:
@@ -41,6 +41,17 @@ fn main() -> Result<()> {
|
||||
};
|
||||
}
|
||||
|
||||
// `portmap` is a local network diagnostic; it needs no server credentials,
|
||||
// so handle it before requiring a username/password.
|
||||
if matches!(cli.command, Some(Commands::Portmap)) {
|
||||
println!(
|
||||
"Testing automatic port mapping for TCP {}…",
|
||||
cli.listener_port
|
||||
);
|
||||
println!("{}", port_mapping::diagnose(cli.listener_port));
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let username = cli.username.ok_or_else(|| {
|
||||
color_eyre::eyre::eyre!(
|
||||
"Username required: use --username or set SOULSEEK_USERNAME env var"
|
||||
@@ -141,6 +152,8 @@ fn main() -> Result<()> {
|
||||
message.as_deref(),
|
||||
listen_secs,
|
||||
),
|
||||
// Handled before the credential check above.
|
||||
Some(Commands::Portmap) => unreachable!(),
|
||||
None => {
|
||||
use ratatui::crossterm::{
|
||||
event::EnableMouseCapture,
|
||||
|
||||
Reference in New Issue
Block a user