refactor: port forwarding (#3850)

* refactor: rename state enum type as tr_port_forwarding_state

* chore: use snake_case for tr_shared struct fields

* refactor: replace tr_shared with tr_port_forwarding

* refactor: make tr_natpmp_state an enum class

* refactor: uniform naming for port-forwarding module

* refactor: move output-only parameters in tr_natpmp::pulse() to return struct

* fix: use a nullptr multicastif if bindaddr is empty

* chore: use PascalCase for enum class values

* chore: clean up port-forwarding #includes

* chore: remove unused tr_port_forwarding::peerPort()
This commit is contained in:
Charles Kerr 2022-09-30 08:59:10 -05:00 committed by GitHub
parent a5ca289f41
commit bf156a97cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 363 additions and 356 deletions

View File

@ -251,7 +251,7 @@
A2EA52321686AC0D00180493 /* quark.h in Headers */ = {isa = PBXBuildFile; fileRef = A2EA52301686AC0D00180493 /* quark.h */; };
A2EB2E7715C8CF2C00FBD5B4 /* QuickLookPlugin.qlgenerator in CopyFiles */ = {isa = PBXBuildFile; fileRef = A2F35BB915C5A0A100EBF632 /* QuickLookPlugin.qlgenerator */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
A2ED7D8F0CEF431B00970975 /* FilterButton.mm in Sources */ = {isa = PBXBuildFile; fileRef = A2ED7D8E0CEF431B00970975 /* FilterButton.mm */; };
A2EE726F14DCCC950093C99A /* natpmp_local.h in Headers */ = {isa = PBXBuildFile; fileRef = A2EE726E14DCCC950093C99A /* natpmp_local.h */; };
A2EE726F14DCCC950093C99A /* port-forwarding-natpmp.h in Headers */ = {isa = PBXBuildFile; fileRef = A2EE726E14DCCC950093C99A /* port-forwarding-natpmp.h */; };
A2F35BBC15C5A0A100EBF632 /* QuickLook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A2F35BBB15C5A0A100EBF632 /* QuickLook.framework */; };
A2F35BC815C5A0A100EBF632 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A2F35BC615C5A0A100EBF632 /* InfoPlist.strings */; };
A2F35BCA15C5A0A100EBF632 /* GenerateThumbnailForURL.mm in Sources */ = {isa = PBXBuildFile; fileRef = A2F35BC915C5A0A100EBF632 /* GenerateThumbnailForURL.mm */; };
@ -292,8 +292,8 @@
BEFC1E290C07861A00B0BB3C /* version.h in Headers */ = {isa = PBXBuildFile; fileRef = BEFC1DF00C07861A00B0BB3C /* version.h */; };
BEFC1E2A0C07861A00B0BB3C /* utils.h in Headers */ = {isa = PBXBuildFile; fileRef = BEFC1DF10C07861A00B0BB3C /* utils.h */; };
BEFC1E2B0C07861A00B0BB3C /* utils.cc in Sources */ = {isa = PBXBuildFile; fileRef = BEFC1DF20C07861A00B0BB3C /* utils.cc */; };
BEFC1E2C0C07861A00B0BB3C /* upnp.h in Headers */ = {isa = PBXBuildFile; fileRef = BEFC1DF30C07861A00B0BB3C /* upnp.h */; };
BEFC1E2D0C07861A00B0BB3C /* upnp.cc in Sources */ = {isa = PBXBuildFile; fileRef = BEFC1DF40C07861A00B0BB3C /* upnp.cc */; };
BEFC1E2C0C07861A00B0BB3C /* port-forwarding-upnp.h in Headers */ = {isa = PBXBuildFile; fileRef = BEFC1DF30C07861A00B0BB3C /* port-forwarding-upnp.h */; };
BEFC1E2D0C07861A00B0BB3C /* port-forwarding-upnp.cc in Sources */ = {isa = PBXBuildFile; fileRef = BEFC1DF40C07861A00B0BB3C /* port-forwarding-upnp.cc */; };
BEFC1E2F0C07861A00B0BB3C /* session.cc in Sources */ = {isa = PBXBuildFile; fileRef = BEFC1DF60C07861A00B0BB3C /* session.cc */; };
BEFC1E320C07861A00B0BB3C /* torrent.cc in Sources */ = {isa = PBXBuildFile; fileRef = BEFC1DF90C07861A00B0BB3C /* torrent.cc */; };
BEFC1E350C07861A00B0BB3C /* port-forwarding.h in Headers */ = {isa = PBXBuildFile; fileRef = BEFC1DFC0C07861A00B0BB3C /* port-forwarding.h */; };
@ -302,7 +302,7 @@
BEFC1E3C0C07861A00B0BB3C /* platform.cc in Sources */ = {isa = PBXBuildFile; fileRef = BEFC1E030C07861A00B0BB3C /* platform.cc */; };
BEFC1E450C07861A00B0BB3C /* net.h in Headers */ = {isa = PBXBuildFile; fileRef = BEFC1E0C0C07861A00B0BB3C /* net.h */; };
BEFC1E460C07861A00B0BB3C /* net.cc in Sources */ = {isa = PBXBuildFile; fileRef = BEFC1E0D0C07861A00B0BB3C /* net.cc */; };
BEFC1E480C07861A00B0BB3C /* natpmp.cc in Sources */ = {isa = PBXBuildFile; fileRef = BEFC1E0F0C07861A00B0BB3C /* natpmp.cc */; };
BEFC1E480C07861A00B0BB3C /* port-forwarding-natpmp.cc in Sources */ = {isa = PBXBuildFile; fileRef = BEFC1E0F0C07861A00B0BB3C /* port-forwarding-natpmp.cc */; };
BEFC1E4D0C07861A00B0BB3C /* session.h in Headers */ = {isa = PBXBuildFile; fileRef = BEFC1E140C07861A00B0BB3C /* session.h */; };
BEFC1E4E0C07861A00B0BB3C /* inout.h in Headers */ = {isa = PBXBuildFile; fileRef = BEFC1E150C07861A00B0BB3C /* inout.h */; };
BEFC1E4F0C07861A00B0BB3C /* inout.cc in Sources */ = {isa = PBXBuildFile; fileRef = BEFC1E160C07861A00B0BB3C /* inout.cc */; };
@ -1009,7 +1009,7 @@
A2EA8E3E0CC3C9830081201C /* fr */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = "<group>"; };
A2ED7D8D0CEF431B00970975 /* FilterButton.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FilterButton.h; sourceTree = "<group>"; };
A2ED7D8E0CEF431B00970975 /* FilterButton.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FilterButton.mm; sourceTree = "<group>"; };
A2EE726E14DCCC950093C99A /* natpmp_local.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = natpmp_local.h; sourceTree = "<group>"; };
A2EE726E14DCCC950093C99A /* port-forwarding-natpmp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = port-forwarding-natpmp.h; sourceTree = "<group>"; };
A2F35BB915C5A0A100EBF632 /* QuickLookPlugin.qlgenerator */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = QuickLookPlugin.qlgenerator; sourceTree = BUILT_PRODUCTS_DIR; };
A2F35BBB15C5A0A100EBF632 /* QuickLook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickLook.framework; path = System/Library/Frameworks/QuickLook.framework; sourceTree = SDKROOT; };
A2F35BBD15C5A0A100EBF632 /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = System/Library/Frameworks/ApplicationServices.framework; sourceTree = SDKROOT; };
@ -1062,8 +1062,8 @@
BEFC1DF00C07861A00B0BB3C /* version.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = "<group>"; };
BEFC1DF10C07861A00B0BB3C /* utils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = "<group>"; };
BEFC1DF20C07861A00B0BB3C /* utils.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = utils.cc; sourceTree = "<group>"; };
BEFC1DF30C07861A00B0BB3C /* upnp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = upnp.h; sourceTree = "<group>"; };
BEFC1DF40C07861A00B0BB3C /* upnp.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = upnp.cc; sourceTree = "<group>"; };
BEFC1DF30C07861A00B0BB3C /* port-forwarding-upnp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = port-forwarding-upnp.h; sourceTree = "<group>"; };
BEFC1DF40C07861A00B0BB3C /* port-forwarding-upnp.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = port-forwarding-upnp.cc; sourceTree = "<group>"; };
BEFC1DF50C07861A00B0BB3C /* transmission.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = transmission.h; sourceTree = "<group>"; };
BEFC1DF60C07861A00B0BB3C /* session.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = session.cc; sourceTree = "<group>"; };
BEFC1DF90C07861A00B0BB3C /* torrent.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = torrent.cc; sourceTree = "<group>"; };
@ -1073,7 +1073,7 @@
BEFC1E030C07861A00B0BB3C /* platform.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = platform.cc; sourceTree = "<group>"; };
BEFC1E0C0C07861A00B0BB3C /* net.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = net.h; sourceTree = "<group>"; };
BEFC1E0D0C07861A00B0BB3C /* net.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = net.cc; sourceTree = "<group>"; };
BEFC1E0F0C07861A00B0BB3C /* natpmp.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = natpmp.cc; sourceTree = "<group>"; };
BEFC1E0F0C07861A00B0BB3C /* port-forwarding-natpmp.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = port-forwarding-natpmp.cc; sourceTree = "<group>"; };
BEFC1E140C07861A00B0BB3C /* session.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = session.h; sourceTree = "<group>"; };
BEFC1E150C07861A00B0BB3C /* inout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = inout.h; sourceTree = "<group>"; };
BEFC1E160C07861A00B0BB3C /* inout.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = inout.cc; sourceTree = "<group>"; };
@ -1650,8 +1650,8 @@
A2BE9C4E0C1E4ADA002D16E6 /* makemeta.cc */,
A2BE9C4F0C1E4ADA002D16E6 /* makemeta.h */,
CAB35C62252F6F5E00552A55 /* mime-types.h */,
A2EE726E14DCCC950093C99A /* natpmp_local.h */,
BEFC1E0F0C07861A00B0BB3C /* natpmp.cc */,
A2EE726E14DCCC950093C99A /* port-forwarding-natpmp.h */,
BEFC1E0F0C07861A00B0BB3C /* port-forwarding-natpmp.cc */,
BEFC1E0D0C07861A00B0BB3C /* net.cc */,
BEFC1E0C0C07861A00B0BB3C /* net.h */,
BEFC1E1A0C07861A00B0BB3C /* open-files.cc */,
@ -1723,8 +1723,8 @@
BEFC1DF50C07861A00B0BB3C /* transmission.h */,
A24621360C769CF400088E81 /* trevent.cc */,
A24621350C769CF400088E81 /* trevent.h */,
BEFC1DF40C07861A00B0BB3C /* upnp.cc */,
BEFC1DF30C07861A00B0BB3C /* upnp.h */,
BEFC1DF40C07861A00B0BB3C /* port-forwarding-upnp.cc */,
BEFC1DF30C07861A00B0BB3C /* port-forwarding-upnp.h */,
BEFC1DF20C07861A00B0BB3C /* utils.cc */,
BEFC1DF10C07861A00B0BB3C /* utils.h */,
A25BFD63167BED3B0039D1AA /* variant-benc.cc */,
@ -2149,7 +2149,7 @@
C1077A51183EB29600634C22 /* file.h in Headers */,
BEFC1E290C07861A00B0BB3C /* version.h in Headers */,
BEFC1E2A0C07861A00B0BB3C /* utils.h in Headers */,
BEFC1E2C0C07861A00B0BB3C /* upnp.h in Headers */,
BEFC1E2C0C07861A00B0BB3C /* port-forwarding-upnp.h in Headers */,
A2AAB65D0DE0CF6200E04DDA /* rpcimpl.h in Headers */,
A2AAB65E0DE0CF6200E04DDA /* rpc-server.h in Headers */,
BEFC1E350C07861A00B0BB3C /* port-forwarding.h in Headers */,
@ -2208,7 +2208,7 @@
C1077A4F183EB29600634C22 /* error.h in Headers */,
A2679295130E00A000CB7464 /* tr-utp.h in Headers */,
A23F29A1132A447400E9A83B /* announcer-common.h in Headers */,
A2EE726F14DCCC950093C99A /* natpmp_local.h in Headers */,
A2EE726F14DCCC950093C99A /* port-forwarding-natpmp.h in Headers */,
A2D77451154CC25700A62B93 /* WebSeedTableView.h in Headers */,
A2A7B32B164F87D400B98C65 /* jsonsl.h in Headers */,
A25BFD6A167BED3B0039D1AA /* variant-common.h in Headers */,
@ -2873,7 +2873,7 @@
files = (
BEFC1E2B0C07861A00B0BB3C /* utils.cc in Sources */,
A2AAB65F0DE0CF6200E04DDA /* rpcimpl.cc in Sources */,
BEFC1E2D0C07861A00B0BB3C /* upnp.cc in Sources */,
BEFC1E2D0C07861A00B0BB3C /* port-forwarding-upnp.cc in Sources */,
A2AAB65C0DE0CF6200E04DDA /* rpc-server.cc in Sources */,
ED8A16402735A8AA000D61F9 /* peer-mgr-active-requests.cc in Sources */,
BEFC1E2F0C07861A00B0BB3C /* session.cc in Sources */,
@ -2884,7 +2884,7 @@
BEFC1E3C0C07861A00B0BB3C /* platform.cc in Sources */,
BEFC1E460C07861A00B0BB3C /* net.cc in Sources */,
C1033E091A3279B800EF44D8 /* crypto-utils.cc in Sources */,
BEFC1E480C07861A00B0BB3C /* natpmp.cc in Sources */,
BEFC1E480C07861A00B0BB3C /* port-forwarding-natpmp.cc in Sources */,
C1077A4E183EB29600634C22 /* error.cc in Sources */,
BEFC1E4F0C07861A00B0BB3C /* inout.cc in Sources */,
BEFC1E530C07861A00B0BB3C /* open-files.cc in Sources */,

View File

@ -33,7 +33,6 @@ set(PROJECT_FILES
log.cc
magnet-metainfo.cc
makemeta.cc
natpmp.cc
net.cc
open-files.cc
peer-io.cc
@ -44,6 +43,8 @@ set(PROJECT_FILES
peer-msgs.cc
platform-quota.cc
platform.cc
port-forwarding-natpmp.cc
port-forwarding-upnp.cc
port-forwarding.cc
quark.cc
resume.cc
@ -69,7 +70,6 @@ set(PROJECT_FILES
tr-udp.cc
tr-utp.cc
trevent.cc
upnp.cc
utils.cc
variant-benc.cc
variant-json.cc
@ -175,7 +175,6 @@ set(${PROJECT_NAME}_PRIVATE_HEADERS
lru-cache.h
magnet-metainfo.h
mime-types.h
natpmp_local.h
net.h
open-files.h
peer-common.h
@ -188,6 +187,8 @@ set(${PROJECT_NAME}_PRIVATE_HEADERS
peer-socket.h
platform-quota.h
platform.h
port-forwarding-natpmp.h
port-forwarding-upnp.h
port-forwarding.h
resume.h
rpc-server.h
@ -203,7 +204,6 @@ set(${PROJECT_NAME}_PRIVATE_HEADERS
tr-lpd.h
tr-utp.h
trevent.h
upnp.h
variant-common.h
verify.h
version.h

View File

@ -15,10 +15,12 @@
#define ENABLE_STRNATPMPERR
#include "natpmp.h"
#define LIBTRANSMISSION_PORT_FORWARDING_MODULE
#include "transmission.h"
#include "natpmp_local.h"
#include "log.h"
#include "net.h" /* tr_netCloseSocket */
#include "port-forwarding-natpmp.h"
#include "port-forwarding.h"
#include "utils.h"
@ -55,23 +57,23 @@ void tr_natpmp::setCommandTime()
command_time_ = tr_time() + CommandWaitSecs;
}
tr_port_forwarding tr_natpmp::pulse(tr_port private_port, bool is_enabled, tr_port* public_port, tr_port* real_private_port)
tr_natpmp::PulseResult tr_natpmp::pulse(tr_port private_port, bool is_enabled)
{
if (is_enabled && state_ == TR_NATPMP_DISCOVER)
if (is_enabled && state_ == State::Discover)
{
int val = initnatpmp(&natpmp_, 0, 0);
logVal("initnatpmp", val);
val = sendpublicaddressrequest(&natpmp_);
logVal("sendpublicaddressrequest", val);
state_ = val < 0 ? TR_NATPMP_ERR : TR_NATPMP_RECV_PUB;
state_ = val < 0 ? State::Err : State::RecvPub;
has_discovered_ = true;
setCommandTime();
}
if (state_ == TR_NATPMP_RECV_PUB && canSendCommand())
if (state_ == State::RecvPub && canSendCommand())
{
natpmpresp_t response;
int const val = readnatpmpresponseorretry(&natpmp_, &response);
auto const val = readnatpmpresponseorretry(&natpmp_, &response);
logVal("readnatpmpresponseorretry", val);
if (val >= 0)
@ -79,31 +81,31 @@ tr_port_forwarding tr_natpmp::pulse(tr_port private_port, bool is_enabled, tr_po
auto str = std::array<char, 128>{};
evutil_inet_ntop(AF_INET, &response.pnu.publicaddress.addr, std::data(str), std::size(str));
tr_logAddInfo(fmt::format(_("Found public address '{address}'"), fmt::arg("address", std::data(str))));
state_ = TR_NATPMP_IDLE;
state_ = State::Idle;
}
else if (val != NATPMP_TRYAGAIN)
{
state_ = TR_NATPMP_ERR;
state_ = State::Err;
}
}
if ((state_ == TR_NATPMP_IDLE || state_ == TR_NATPMP_ERR) && is_mapped_ && (!is_enabled || private_port_ != private_port))
if ((state_ == State::Idle || state_ == State::Err) && is_mapped_ && (!is_enabled || private_port_ != private_port))
{
state_ = TR_NATPMP_SEND_UNMAP;
state_ = State::SendUnmap;
}
if (state_ == TR_NATPMP_SEND_UNMAP && canSendCommand())
if (state_ == State::SendUnmap && canSendCommand())
{
int const val = sendnewportmappingrequest(&natpmp_, NATPMP_PROTOCOL_TCP, private_port_.host(), public_port_.host(), 0);
auto const val = sendnewportmappingrequest(&natpmp_, NATPMP_PROTOCOL_TCP, private_port_.host(), public_port_.host(), 0);
logVal("sendnewportmappingrequest", val);
state_ = val < 0 ? TR_NATPMP_ERR : TR_NATPMP_RECV_UNMAP;
state_ = val < 0 ? State::Err : State::RecvUnmap;
setCommandTime();
}
if (state_ == TR_NATPMP_RECV_UNMAP)
if (state_ == State::RecvUnmap)
{
natpmpresp_t resp;
int const val = readnatpmpresponseorretry(&natpmp_, &resp);
auto resp = natpmpresp_t{};
auto const val = readnatpmpresponseorretry(&natpmp_, &resp);
logVal("readnatpmpresponseorretry", val);
if (val >= 0)
@ -116,50 +118,50 @@ tr_port_forwarding tr_natpmp::pulse(tr_port private_port, bool is_enabled, tr_po
{
private_port_.clear();
public_port_.clear();
state_ = TR_NATPMP_IDLE;
state_ = State::Idle;
is_mapped_ = false;
}
}
else if (val != NATPMP_TRYAGAIN)
{
state_ = TR_NATPMP_ERR;
state_ = State::Err;
}
}
if (state_ == TR_NATPMP_IDLE)
if (state_ == State::Idle)
{
if (is_enabled && !is_mapped_ && has_discovered_)
{
state_ = TR_NATPMP_SEND_MAP;
state_ = State::SendMap;
}
else if (is_mapped_ && tr_time() >= renew_time_)
{
state_ = TR_NATPMP_SEND_MAP;
state_ = State::SendMap;
}
}
if (state_ == TR_NATPMP_SEND_MAP && canSendCommand())
if (state_ == State::SendMap && canSendCommand())
{
int const val = sendnewportmappingrequest(
auto const val = sendnewportmappingrequest(
&natpmp_,
NATPMP_PROTOCOL_TCP,
private_port.host(),
private_port.host(),
LifetimeSecs);
logVal("sendnewportmappingrequest", val);
state_ = val < 0 ? TR_NATPMP_ERR : TR_NATPMP_RECV_MAP;
state_ = val < 0 ? State::Err : State::RecvMap;
setCommandTime();
}
if (state_ == TR_NATPMP_RECV_MAP)
if (state_ == State::RecvMap)
{
natpmpresp_t resp;
int const val = readnatpmpresponseorretry(&natpmp_, &resp);
auto resp = natpmpresp_t{};
auto const val = readnatpmpresponseorretry(&natpmp_, &resp);
logVal("readnatpmpresponseorretry", val);
if (val >= 0)
{
state_ = TR_NATPMP_IDLE;
state_ = State::Idle;
is_mapped_ = true;
renew_time_ = tr_time() + (resp.pnu.newportmapping.lifetime / 2);
private_port_ = tr_port::fromHost(resp.pnu.newportmapping.privateport);
@ -168,30 +170,28 @@ tr_port_forwarding tr_natpmp::pulse(tr_port private_port, bool is_enabled, tr_po
}
else if (val != NATPMP_TRYAGAIN)
{
state_ = TR_NATPMP_ERR;
state_ = State::Err;
}
}
switch (state_)
{
case TR_NATPMP_IDLE:
*public_port = public_port_;
*real_private_port = private_port_;
return is_mapped_ ? TR_PORT_MAPPED : TR_PORT_UNMAPPED;
case State::Idle:
return { is_mapped_ ? TR_PORT_MAPPED : TR_PORT_UNMAPPED, public_port_, private_port_ };
case TR_NATPMP_DISCOVER:
return TR_PORT_UNMAPPED;
case State::Discover:
return { TR_PORT_UNMAPPED, {}, {} };
case TR_NATPMP_RECV_PUB:
case TR_NATPMP_SEND_MAP:
case TR_NATPMP_RECV_MAP:
return TR_PORT_MAPPING;
case State::RecvPub:
case State::SendMap:
case State::RecvMap:
return { TR_PORT_MAPPING, {}, {} };
case TR_NATPMP_SEND_UNMAP:
case TR_NATPMP_RECV_UNMAP:
return TR_PORT_UNMAPPING;
case State::SendUnmap:
case State::RecvUnmap:
return { TR_PORT_UNMAPPING, {}, {} };
default:
return TR_PORT_ERROR;
return { TR_PORT_ERROR, {}, {} };
}
}

View File

@ -5,14 +5,14 @@
#pragma once
#ifndef __TRANSMISSION__
#error only libtransmission should #include this header.
#ifndef LIBTRANSMISSION_PORT_FORWARDING_MODULE
#error only the libtransmission port forwarding module should #include this header.
#endif
#include <ctime> // time_t
#include <cstdint>
#include "transmission.h" // tr_port_forwarding
#include "transmission.h" // tr_port_forwarding_state
#include "natpmp.h"
#include "net.h" // tr_port
@ -35,19 +35,27 @@ public:
return renew_time_;
}
tr_port_forwarding pulse(tr_port port, bool is_enabled, tr_port* public_port, tr_port* real_private_port);
struct PulseResult
{
tr_port_forwarding_state state = TR_PORT_ERROR;
tr_port public_port = {};
tr_port private_port = {};
};
PulseResult pulse(tr_port port, bool is_enabled);
private:
enum tr_natpmp_state
enum class State
{
TR_NATPMP_IDLE,
TR_NATPMP_ERR,
TR_NATPMP_DISCOVER,
TR_NATPMP_RECV_PUB,
TR_NATPMP_SEND_MAP,
TR_NATPMP_RECV_MAP,
TR_NATPMP_SEND_UNMAP,
TR_NATPMP_RECV_UNMAP
Idle,
Err,
Discover,
RecvPub,
SendMap,
RecvMap,
SendUnmap,
RecvUnmap
};
static constexpr auto LifetimeSecs = uint32_t{ 3600 };
@ -64,7 +72,7 @@ private:
time_t renew_time_ = 0;
time_t command_time_ = 0;
tr_natpmp_state state_ = TR_NATPMP_DISCOVER;
State state_ = State::Discover;
bool has_discovered_ = false;
bool is_mapped_ = false;

View File

@ -22,42 +22,44 @@
#include <miniupnp/upnpcommands.h>
#endif
#define LIBTRANSMISSION_PORT_FORWARDING_MODULE
#include "transmission.h"
#include "log.h"
#include "port-forwarding-upnp.h"
#include "port-forwarding.h"
#include "session.h"
#include "tr-assert.h"
#include "upnp.h"
#include "utils.h"
#include "utils.h" // for _(), tr_strerror()
namespace
{
enum class UpnpState
{
IDLE,
FAILED,
WILL_DISCOVER, // next action is upnpDiscover()
DISCOVERING, // currently making blocking upnpDiscover() call in a worker thread
WILL_MAP, // next action is UPNP_AddPortMapping()
WILL_UNMAP // next action is UPNP_DeletePortMapping()
Idle,
Failed,
WillDiscover, // next action is upnpDiscover()
Discovering, // currently making blocking upnpDiscover() call in a worker thread
WillMap, // next action is UPNP_AddPortMapping()
WillUnmap // next action is UPNP_DeletePortMapping()
};
constexpr tr_port_forwarding portFwdState(UpnpState upnp_state, bool is_mapped)
constexpr auto portFwdState(UpnpState upnp_state, bool is_mapped)
{
switch (upnp_state)
{
case UpnpState::WILL_DISCOVER:
case UpnpState::DISCOVERING:
case UpnpState::WillDiscover:
case UpnpState::Discovering:
return TR_PORT_UNMAPPED;
case UpnpState::WILL_MAP:
case UpnpState::WillMap:
return TR_PORT_MAPPING;
case UpnpState::WILL_UNMAP:
case UpnpState::WillUnmap:
return TR_PORT_UNMAPPING;
case UpnpState::IDLE:
case UpnpState::Idle:
return is_mapped ? TR_PORT_MAPPED : TR_PORT_UNMAPPED;
default: // UpnpState::FAILED:
@ -79,8 +81,8 @@ struct tr_upnp
{
TR_ASSERT(!isMapped);
TR_ASSERT(
state == UpnpState::IDLE || state == UpnpState::FAILED || state == UpnpState::WILL_DISCOVER ||
state == UpnpState::DISCOVERING);
state == UpnpState::Idle || state == UpnpState::Failed || state == UpnpState::WillDiscover ||
state == UpnpState::Discovering);
FreeUPNPUrls(&urls);
}
@ -91,7 +93,7 @@ struct tr_upnp
tr_port port;
std::string lanaddr;
bool isMapped = false;
UpnpState state = UpnpState::WILL_DISCOVER;
UpnpState state = UpnpState::WillDiscover;
// Used to return the results of upnpDiscover() from a worker thread
// to be processed without blocking in tr_upnpPulse().
@ -248,7 +250,10 @@ enum
static auto* discoverThreadfunc(std::string bindaddr) // NOLINT performance-unnecessary-value-param
{
return tr_upnpDiscover(2000, bindaddr.c_str());
// If multicastif is not NULL, it will be used instead of the default
// multicast interface for sending SSDP discover packets.
char const* multicastif = std::empty(bindaddr) ? nullptr : bindaddr.c_str();
return tr_upnpDiscover(2000, multicastif);
}
template<typename T>
@ -257,20 +262,20 @@ static bool isFutureReady(std::future<T> const& future)
return future.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
}
tr_port_forwarding tr_upnpPulse(tr_upnp* handle, tr_port port, bool is_enabled, bool do_port_check, std::string bindaddr)
tr_port_forwarding_state tr_upnpPulse(tr_upnp* handle, tr_port port, bool is_enabled, bool do_port_check, std::string bindaddr)
{
if (is_enabled && handle->state == UpnpState::WILL_DISCOVER)
if (is_enabled && handle->state == UpnpState::WillDiscover)
{
TR_ASSERT(!handle->discover_future);
auto task = std::packaged_task<UPNPDev*(std::string)>{ discoverThreadfunc };
handle->discover_future = task.get_future();
handle->state = UpnpState::DISCOVERING;
handle->state = UpnpState::Discovering;
std::thread(std::move(task), std::move(bindaddr)).detach();
}
if (is_enabled && handle->state == UpnpState::DISCOVERING && handle->discover_future &&
if (is_enabled && handle->state == UpnpState::Discovering && handle->discover_future &&
isFutureReady(*handle->discover_future))
{
auto* const devlist = handle->discover_future->get();
@ -283,13 +288,13 @@ tr_port_forwarding tr_upnpPulse(tr_upnp* handle, tr_port port, bool is_enabled,
{
tr_logAddInfo(fmt::format(_("Found Internet Gateway Device '{url}'"), fmt::arg("url", handle->urls.controlURL)));
tr_logAddInfo(fmt::format(_("Local Address is '{address}'"), fmt::arg("address", std::data(handle->lanaddr))));
handle->state = UpnpState::IDLE;
handle->state = UpnpState::Idle;
handle->hasDiscovered = true;
handle->lanaddr = std::data(lanaddr);
}
else
{
handle->state = UpnpState::FAILED;
handle->state = UpnpState::Failed;
tr_logAddDebug(fmt::format("UPNP_GetValidIGD failed: {} ({})", tr_strerror(errno), errno));
tr_logAddDebug("If your router supports UPnP, please make sure UPnP is enabled!");
}
@ -297,9 +302,9 @@ tr_port_forwarding tr_upnpPulse(tr_upnp* handle, tr_port port, bool is_enabled,
freeUPNPDevlist(devlist);
}
if ((handle->state == UpnpState::IDLE) && (handle->isMapped) && (!is_enabled || handle->port != port))
if ((handle->state == UpnpState::Idle) && (handle->isMapped) && (!is_enabled || handle->port != port))
{
handle->state = UpnpState::WILL_UNMAP;
handle->state = UpnpState::WillUnmap;
}
if (is_enabled && handle->isMapped && do_port_check &&
@ -310,7 +315,7 @@ tr_port_forwarding tr_upnpPulse(tr_upnp* handle, tr_port port, bool is_enabled,
handle->isMapped = false;
}
if (handle->state == UpnpState::WILL_UNMAP)
if (handle->state == UpnpState::WillUnmap)
{
tr_upnpDeletePortMapping(handle, "TCP", handle->port);
tr_upnpDeletePortMapping(handle, "UDP", handle->port);
@ -321,16 +326,16 @@ tr_port_forwarding tr_upnpPulse(tr_upnp* handle, tr_port port, bool is_enabled,
fmt::arg("type", handle->data.first.servicetype)));
handle->isMapped = false;
handle->state = UpnpState::IDLE;
handle->state = UpnpState::Idle;
handle->port = {};
}
if ((handle->state == UpnpState::IDLE) && is_enabled && !handle->isMapped)
if ((handle->state == UpnpState::Idle) && is_enabled && !handle->isMapped)
{
handle->state = UpnpState::WILL_MAP;
handle->state = UpnpState::WillMap;
}
if (handle->state == UpnpState::WILL_MAP)
if (handle->state == UpnpState::WillMap)
{
errno = 0;
@ -340,7 +345,7 @@ tr_port_forwarding tr_upnpPulse(tr_upnp* handle, tr_port port, bool is_enabled,
}
else
{
auto const desc = fmt::format(FMT_STRING("{:s} at {:d}"), TR_NAME, port.host());
auto const desc = fmt::format(FMT_STRING("Transmission at {:d}"), port.host());
int const err_tcp = tr_upnpAddPortMapping(handle, "TCP", port, desc.c_str());
int const err_udp = tr_upnpAddPortMapping(handle, "UDP", port, desc.c_str());
@ -358,13 +363,13 @@ tr_port_forwarding tr_upnpPulse(tr_upnp* handle, tr_port port, bool is_enabled,
{
tr_logAddInfo(fmt::format(_("Port {port} is forwarded"), fmt::arg("port", port.host())));
handle->port = port;
handle->state = UpnpState::IDLE;
handle->state = UpnpState::Idle;
}
else
{
tr_logAddInfo(_("If your router supports UPnP, please make sure UPnP is enabled!"));
handle->port = {};
handle->state = UpnpState::FAILED;
handle->state = UpnpState::Failed;
}
}

View File

@ -5,8 +5,8 @@
#pragma once
#ifndef __TRANSMISSION__
#error only libtransmission should #include this header.
#ifndef LIBTRANSMISSION_PORT_FORWARDING_MODULE
#error only the libtransmission port forwarding module should #include this header.
#endif
/**
@ -26,6 +26,6 @@ tr_upnp* tr_upnpInit(void);
void tr_upnpClose(tr_upnp*);
tr_port_forwarding tr_upnpPulse(tr_upnp*, tr_port port, bool is_enabled, bool do_port_check, std::string);
tr_port_forwarding_state tr_upnpPulse(tr_upnp*, tr_port port, bool is_enabled, bool do_port_check, std::string);
/* @} */

View File

@ -9,241 +9,232 @@
#include <fmt/core.h>
#define LIBTRANSMISSION_PORT_FORWARDING_MODULE
#include "transmission.h"
#include "natpmp_local.h"
#include "log.h"
#include "net.h"
#include "peer-mgr.h"
#include "port-forwarding-natpmp.h"
#include "port-forwarding-upnp.h"
#include "port-forwarding.h"
#include "session.h"
#include "timer.h"
#include "torrent.h"
#include "tr-assert.h"
#include "upnp.h"
#include "utils.h" // for _()
using namespace std::literals;
struct tr_shared
class tr_port_forwarding_impl final : public tr_port_forwarding
{
explicit tr_shared(tr_session& session_in)
: session{ session_in }
public:
explicit tr_port_forwarding_impl(tr_session& session)
: session_{ session }
, timer_maker_{ session.timerMaker() }
{
}
tr_session& session;
~tr_port_forwarding_impl() override
{
is_shutting_down_ = true;
stopForwarding();
}
bool isEnabled = false;
bool isShuttingDown = false;
bool doPortCheck = false;
tr_port_forwarding_impl(tr_port_forwarding_impl&&) = delete;
tr_port_forwarding_impl(tr_port_forwarding_impl const&) = delete;
tr_port_forwarding_impl& operator=(tr_port_forwarding_impl&&) = delete;
tr_port_forwarding_impl& operator=(tr_port_forwarding_impl const&) = delete;
tr_port_forwarding natpmpStatus = TR_PORT_UNMAPPED;
tr_port_forwarding upnpStatus = TR_PORT_UNMAPPED;
void portChanged() override
{
if (!is_enabled_)
{
return;
}
tr_upnp* upnp = nullptr;
std::unique_ptr<tr_natpmp> natpmp;
stopTimer();
natPulse(false);
startTimer();
}
std::unique_ptr<libtransmission::Timer> timer;
void setEnabled(bool enabled) override
{
if (enabled)
{
is_enabled_ = true;
startTimer();
}
else
{
is_enabled_ = false;
stopForwarding();
}
}
[[nodiscard]] bool isEnabled() const noexcept override
{
return is_enabled_;
}
[[nodiscard]] tr_port_forwarding_state state() const noexcept override
{
return std::max(natpmp_state_, upnp_state_);
}
private:
void stopTimer()
{
timer_.reset();
}
void stopForwarding()
{
tr_logAddTrace("stopped");
natPulse(false);
natpmp_.reset();
natpmp_state_ = TR_PORT_UNMAPPED;
tr_upnpClose(upnp_);
upnp_ = nullptr;
upnp_state_ = TR_PORT_UNMAPPED;
stopTimer();
}
void startTimer()
{
timer_ = timer_maker_.create([this]() { this->onTimer(); });
restartTimer();
}
void restartTimer()
{
if (!timer_)
{
return;
}
// when to wake up again
switch (state())
{
case TR_PORT_MAPPED:
// if we're mapped, everything is fine... check back at `renew_time`
// to renew the port forwarding if it's expired
do_port_check_ = true;
if (auto const now = tr_time(); natpmp_->renewTime() > now)
{
timer_->startSingleShot(std::chrono::seconds{ natpmp_->renewTime() - now });
}
else // ???
{
timer_->startSingleShot(1min);
}
break;
case TR_PORT_ERROR:
// some kind of an error. wait a minute and retry
timer_->startSingleShot(1min);
break;
default:
// in progress. pulse frequently.
timer_->startSingleShot(333ms);
break;
}
}
void onTimer()
{
TR_ASSERT(timer_);
// do something
natPulse(do_port_check_);
do_port_check_ = false;
// set up the timer for the next pulse
restartTimer();
}
static constexpr char const* getNatStateStr(int state)
{
switch (state)
{
case TR_PORT_MAPPING:
return _("Starting");
case TR_PORT_MAPPED:
return _("Forwarded");
case TR_PORT_UNMAPPING:
return _("Stopping");
case TR_PORT_UNMAPPED:
return _("Not forwarded");
default:
return "???";
}
}
void natPulse(bool do_check)
{
auto& session = session_;
auto const is_enabled = is_enabled_ && !is_shutting_down_;
if (!natpmp_)
{
natpmp_ = std::make_unique<tr_natpmp>();
}
if (upnp_ == nullptr)
{
upnp_ = tr_upnpInit();
}
auto const old_state = state();
auto const result = natpmp_->pulse(session.private_peer_port, is_enabled);
natpmp_state_ = result.state;
if (!std::empty(result.public_port) && !std::empty(result.private_port))
{
session.public_peer_port = result.public_port;
session.private_peer_port = result.private_port;
tr_logAddInfo(fmt::format(
_("Mapped private port {private_port} to public port {public_port}"),
fmt::arg("public_port", session.public_peer_port.host()),
fmt::arg("private_port", session.private_peer_port.host())));
}
upnp_state_ = tr_upnpPulse(upnp_, session.private_peer_port, is_enabled, do_check, session.bind_ipv4.readable());
if (auto const new_state = state(); new_state != old_state)
{
tr_logAddInfo(fmt::format(
_("State changed from '{old_state}' to '{state}'"),
fmt::arg("old_state", getNatStateStr(old_state)),
fmt::arg("state", getNatStateStr(new_state))));
}
}
tr_session& session_;
libtransmission::TimerMaker& timer_maker_;
bool is_enabled_ = false;
bool is_shutting_down_ = false;
bool do_port_check_ = false;
tr_port_forwarding_state natpmp_state_ = TR_PORT_UNMAPPED;
tr_port_forwarding_state upnp_state_ = TR_PORT_UNMAPPED;
tr_upnp* upnp_ = nullptr;
std::unique_ptr<tr_natpmp> natpmp_;
std::unique_ptr<libtransmission::Timer> timer_;
};
/***
****
***/
static char const* getNatStateStr(int state)
std::unique_ptr<tr_port_forwarding> tr_port_forwarding::create(tr_session& session)
{
switch (state)
{
case TR_PORT_MAPPING:
return _("Starting");
case TR_PORT_MAPPED:
return _("Forwarded");
case TR_PORT_UNMAPPING:
return _("Stopping");
case TR_PORT_UNMAPPED:
return _("Not forwarded");
default:
return "???";
}
}
static void natPulse(tr_shared* s, bool do_check)
{
auto& session = s->session;
tr_port const private_peer_port = session.private_peer_port;
bool const is_enabled = s->isEnabled && !s->isShuttingDown;
if (!s->natpmp)
{
s->natpmp = std::make_unique<tr_natpmp>();
}
if (s->upnp == nullptr)
{
s->upnp = tr_upnpInit();
}
auto const old_status = tr_sharedTraversalStatus(s);
auto public_peer_port = tr_port{};
auto received_private_port = tr_port{};
s->natpmpStatus = s->natpmp->pulse(private_peer_port, is_enabled, &public_peer_port, &received_private_port);
if (s->natpmpStatus == TR_PORT_MAPPED)
{
session.public_peer_port = public_peer_port;
session.private_peer_port = received_private_port;
tr_logAddInfo(fmt::format(
_("Mapped private port {private_port} to public port {public_port}"),
fmt::arg("public_port", session.public_peer_port.host()),
fmt::arg("private_port", session.private_peer_port.host())));
}
s->upnpStatus = tr_upnpPulse(s->upnp, private_peer_port, is_enabled, do_check, session.bind_ipv4.readable());
auto const new_status = tr_sharedTraversalStatus(s);
if (new_status != old_status)
{
tr_logAddInfo(fmt::format(
_("State changed from '{old_state}' to '{state}'"),
fmt::arg("old_state", getNatStateStr(old_status)),
fmt::arg("state", getNatStateStr(new_status))));
}
}
static void restartTimer(tr_shared* s)
{
auto& timer = s->timer;
if (!timer)
{
return;
}
// when to wake up again
switch (tr_sharedTraversalStatus(s))
{
case TR_PORT_MAPPED:
// if we're mapped, everything is fine... check back at `renew_time`
// to renew the port forwarding if it's expired
s->doPortCheck = true;
if (auto const now = tr_time(); s->natpmp->renewTime() > now)
{
timer->startSingleShot(std::chrono::seconds{ s->natpmp->renewTime() - now });
}
else // ???
{
timer->startSingleShot(1min);
}
break;
case TR_PORT_ERROR:
// some kind of an error. wait a minute and retry
timer->startSingleShot(1min);
break;
default:
// in progress. pulse frequently.
timer->startSingleShot(333ms);
break;
}
}
static void onTimer(void* vshared)
{
auto* s = static_cast<tr_shared*>(vshared);
TR_ASSERT(s != nullptr);
TR_ASSERT(s->timer);
/* do something */
natPulse(s, s->doPortCheck);
s->doPortCheck = false;
/* set up the timer for the next pulse */
restartTimer(s);
}
/***
****
***/
tr_shared* tr_sharedInit(tr_session& session)
{
return new tr_shared{ session };
}
static void stop_timer(tr_shared* s)
{
s->timer.reset();
}
static void stop_forwarding(tr_shared* s)
{
tr_logAddTrace("stopped");
natPulse(s, false);
s->natpmp.reset();
s->natpmpStatus = TR_PORT_UNMAPPED;
tr_upnpClose(s->upnp);
s->upnp = nullptr;
s->upnpStatus = TR_PORT_UNMAPPED;
stop_timer(s);
}
void tr_sharedClose(tr_session& session)
{
tr_shared* shared = session.shared;
shared->isShuttingDown = true;
stop_forwarding(shared);
shared->session.shared = nullptr;
delete shared;
}
static void start_timer(tr_shared* s)
{
s->timer = s->session.timerMaker().create(onTimer, s);
restartTimer(s);
}
void tr_sharedTraversalEnable(tr_shared* s, bool is_enable)
{
if (is_enable)
{
s->isEnabled = true;
start_timer(s);
}
else
{
s->isEnabled = false;
stop_forwarding(s);
}
}
void tr_sharedPortChanged(tr_session& session)
{
auto* const s = session.shared;
if (s->isEnabled)
{
stop_timer(s);
natPulse(s, false);
start_timer(s);
}
}
bool tr_sharedTraversalIsEnabled(tr_shared const* s)
{
return s->isEnabled;
}
int tr_sharedTraversalStatus(tr_shared const* s)
{
return std::max(s->natpmpStatus, s->upnpStatus);
return std::make_unique<tr_port_forwarding_impl>(session);
}

View File

@ -9,22 +9,24 @@
#error only libtransmission should #include this header.
#endif
#include "net.h" // tr_port
#include <memory> // for std::unique_ptr
#include "transmission.h" // for tr_port_forwarding_state
struct tr_bindsockets;
struct tr_session;
struct tr_shared;
tr_shared* tr_sharedInit(tr_session&);
class tr_port_forwarding
{
public:
virtual ~tr_port_forwarding() = default;
void tr_sharedClose(tr_session&);
virtual void portChanged() = 0;
void tr_sharedPortChanged(tr_session&);
virtual void setEnabled(bool enabled) = 0;
void tr_sharedTraversalEnable(tr_shared*, bool is_enabled);
[[nodiscard]] virtual bool isEnabled() const = 0;
tr_port tr_sharedGetPeerPort(tr_shared const* s);
[[nodiscard]] virtual tr_port_forwarding_state state() const = 0;
bool tr_sharedTraversalIsEnabled(tr_shared const* s);
int tr_sharedTraversalStatus(tr_shared const*);
[[nodiscard]] static std::unique_ptr<tr_port_forwarding> create(tr_session&);
};

View File

@ -731,7 +731,7 @@ void tr_session::initImpl(init_data& data)
this->peerMgr = tr_peerMgrNew(this);
this->shared = tr_sharedInit(*this);
this->port_forwarding_ = tr_port_forwarding::create(*this);
/**
*** Blocklist
@ -1262,7 +1262,7 @@ static void peerPortChanged(tr_session* const session)
open_incoming_peer_port(session);
}
tr_sharedPortChanged(*session);
session->port_forwarding_->portChanged();
for (auto* const tor : session->torrents())
{
@ -1312,11 +1312,11 @@ bool tr_sessionGetPeerPortRandomOnStart(tr_session const* session)
return session->isPortRandom();
}
tr_port_forwarding tr_sessionGetPortForwarding(tr_session const* session)
tr_port_forwarding_state tr_sessionGetPortForwarding(tr_session const* session)
{
TR_ASSERT(session != nullptr);
return tr_port_forwarding(tr_sharedTraversalStatus(session->shared));
return session->port_forwarding_->state();
}
/***
@ -1812,7 +1812,7 @@ void tr_session::closeImplStart()
now_timer_.reset();
verifier_.reset();
tr_sharedClose(*this);
port_forwarding_.reset();
close_incoming_peer_port(this);
this->rpc_server_.reset();
@ -1910,17 +1910,17 @@ void tr_sessionClose(tr_session* session)
tr_wait_msec(10);
}
/* "shared" and "tracker" have live sockets,
/* "port_forwarding" and "tracker" have live sockets,
* so we need to keep the transmission thread alive
* for a bit while they tell the router & tracker
* that we're closing now */
while ((session->shared != nullptr || !session->web->isClosed() || session->announcer != nullptr ||
while ((session->port_forwarding_ || !session->web->isClosed() || session->announcer != nullptr ||
session->announcer_udp != nullptr) &&
!deadlineReached(deadline))
{
tr_logAddTrace(fmt::format(
"waiting on port unmap ({}) or announcer ({})... now {} deadline {}",
fmt::ptr(session->shared),
fmt::ptr(session->port_forwarding_.get()),
fmt::ptr(session->announcer),
time(nullptr),
deadline));
@ -2218,14 +2218,14 @@ tr_bandwidth& tr_session::getBandwidthGroup(std::string_view name)
void tr_sessionSetPortForwardingEnabled(tr_session* session, bool enabled)
{
tr_runInEventThread(session, tr_sharedTraversalEnable, session->shared, enabled);
tr_runInEventThread(session, [session, enabled]() { session->port_forwarding_->setEnabled(enabled); });
}
bool tr_sessionIsPortForwardingEnabled(tr_session const* session)
{
TR_ASSERT(session != nullptr);
return tr_sharedTraversalIsEnabled(session->shared);
return session->port_forwarding_->isEnabled();
}
/***

View File

@ -56,6 +56,7 @@ struct evdns_base;
class tr_rpc_server;
class tr_web;
class tr_lpd;
class tr_port_forwarding;
struct BlocklistFile;
struct struct_utp_context;
struct tr_announcer;
@ -550,7 +551,7 @@ public:
}
struct tr_peerMgr* peerMgr = nullptr;
struct tr_shared* shared = nullptr;
std::unique_ptr<tr_port_forwarding> port_forwarding_;
std::unique_ptr<Cache> cache;

View File

@ -474,7 +474,7 @@ void tr_sessionSetPeerPortRandomOnStart(tr_session* session, bool random);
bool tr_sessionGetPeerPortRandomOnStart(tr_session const* session);
enum tr_port_forwarding
enum tr_port_forwarding_state
{
TR_PORT_ERROR,
TR_PORT_UNMAPPED,
@ -483,7 +483,7 @@ enum tr_port_forwarding
TR_PORT_MAPPED
};
tr_port_forwarding tr_sessionGetPortForwarding(tr_session const* session);
tr_port_forwarding_state tr_sessionGetPortForwarding(tr_session const* session);
enum tr_direction
{

View File

@ -449,7 +449,7 @@
- (void)updatePortStatus
{
tr_port_forwarding const fwd = tr_sessionGetPortForwarding(self.fHandle);
auto const fwd = tr_sessionGetPortForwarding(self.fHandle);
int const port = tr_sessionGetPeerPort(self.fHandle);
BOOL natStatusChanged = (self.fNatStatus != fwd);
BOOL peerPortChanged = (self.fPeerPort != port);