From 4c6f7afdc7b5208cc121307160ac84b9d23873f6 Mon Sep 17 00:00:00 2001 From: Auska Date: Tue, 11 Aug 2026 06:29:07 +0800 Subject: [PATCH] Add network.local_port commands for tracker port reporting Mirror the network.local_address.* command family for ports: - network.local_port report the best-match local port - network.local_port.set set both the ipv4 and ipv6 local ports - network.local_port.ipv4(.set) get/set the ipv4 local port only - network.local_port.ipv6(.set) get/set the ipv6 local port only Values are restricted to 0-65535; 0 (default) means unset, and trackers then report the listening port. Why: behind multiple layers of NAT the port peers must connect to can differ from the port rtorrent is listening on. These commands let the user manually advertise the forwarded public port per address family, e.g.: network.local_port.ipv4.set = 6881 network.local_port.ipv6.set = 6882 network.local_port is marked safe for RPC use alongside network.local_address. --- doc/rtorrent.rc | 8 ++++++++ src/command_network.cc | 20 ++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/doc/rtorrent.rc b/doc/rtorrent.rc index aa2e6fdf..eceb12c4 100644 --- a/doc/rtorrent.rc +++ b/doc/rtorrent.rc @@ -63,6 +63,14 @@ #network.local_address.set = 127.0.0.1 #network.local_address.set = rakshasa.no +# The port reported to the tracker, separate for ipv4/ipv6. A value of 0 +# (the default) falls back to reporting the listening port. network.local_port.set +# sets both the ipv4 and ipv6 ports at once. +# +#network.local_port.set = 6881 +#network.local_port.ipv4.set = 6881 +#network.local_port.ipv6.set = 6882 + # The IP address the listening socket and outgoing connections is # bound to. # diff --git a/src/command_network.cc b/src/command_network.cc index a8c6b027..23530f37 100644 --- a/src/command_network.cc +++ b/src/command_network.cc @@ -379,6 +379,25 @@ initialize_command_network() { CMD_ANY ("network.local_address.ipv6", [nw_config](auto, auto) { return nw_config->local_inet6_address_str(); }); CMD_ANY_STRING_V("network.local_address.ipv6.set", [nw_config](auto, auto& str) { return nw_config->set_local_inet6_address_str(str); }); + CMD_ANY ("network.local_port", [nw_config](auto, auto) { return nw_config->local_port_best_match(); }); + CMD_ANY_VALUE_V ("network.local_port.set", [nw_config](auto, auto& value) { + if (value < 0 || value > 65535) + throw torrent::input_error("Invalid local port number."); + return nw_config->set_local_port(value); + }); + CMD_ANY ("network.local_port.ipv4", [nw_config](auto, auto) { return nw_config->local_inet_port(); }); + CMD_ANY_VALUE_V ("network.local_port.ipv4.set", [nw_config](auto, auto& value) { + if (value < 0 || value > 65535) + throw torrent::input_error("Invalid local port number."); + return nw_config->set_local_inet_port(value); + }); + CMD_ANY ("network.local_port.ipv6", [nw_config](auto, auto) { return nw_config->local_inet6_port(); }); + CMD_ANY_VALUE_V ("network.local_port.ipv6.set", [nw_config](auto, auto& value) { + if (value < 0 || value > 65535) + throw torrent::input_error("Invalid local port number."); + return nw_config->set_local_inet6_port(value); + }); + CMD_ANY ("network.proxy.global", [](auto, auto) { return torrent::runtime::proxy_manager()->proxy_url(); }); CMD_ANY_STRING_V("network.proxy.global.set", [](auto, auto& str) { return torrent::runtime::proxy_manager()->set_proxy_url(str); }); CMD_ANY ("network.proxy.http", [](auto, auto) { return torrent::runtime::proxy_manager()->http_proxy_url(); }); @@ -437,6 +456,7 @@ initialize_command_network() { rpc::rpc.mark_safe("network.receive_buffer.size"); rpc::rpc.mark_safe("network.bind_address"); rpc::rpc.mark_safe("network.local_address"); + rpc::rpc.mark_safe("network.local_port"); rpc::rpc.mark_safe("network.xmlrpc.size_limit"); rpc::rpc.mark_safe("network.open_sockets");