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:
michel
2026-07-19 21:46:46 +02:00
parent 84c571767a
commit 2d5fc26db7
5 changed files with 271 additions and 26 deletions
+10
View File
@@ -141,6 +141,16 @@ you'll see a log line suggesting you forward the port manually.
`--listener-port` you chose) to this machine on your router.
- Pass `--disable-listener` to turn the listener (and port mapping) off.
Check whether it works on **your** network without launching the whole client:
```bash
soulseek-rs portmap
```
It tries to open the port via UPnP/NAT-PMP and prints whether your router
allowed it (and your external address), then removes the test mapping. If it
reports failure, enable UPnP on your router or forward the port manually.
If both you and a peer are behind routers with no forwarded port, browsing that
peer can't work — that's a fundamental Soulseek/peer-to-peer limitation, not a
bug.