From bf156a97cff8700f99d8794d7e67f7e4dc382e1c Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 30 Sep 2022 08:59:10 -0500 Subject: [PATCH] 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() --- Transmission.xcodeproj/project.pbxproj | 32 +- libtransmission/CMakeLists.txt | 8 +- .../{natpmp.cc => port-forwarding-natpmp.cc} | 88 ++-- ...atpmp_local.h => port-forwarding-natpmp.h} | 36 +- .../{upnp.cc => port-forwarding-upnp.cc} | 75 ++-- .../{upnp.h => port-forwarding-upnp.h} | 6 +- libtransmission/port-forwarding.cc | 421 +++++++++--------- libtransmission/port-forwarding.h | 24 +- libtransmission/session.cc | 20 +- libtransmission/session.h | 3 +- libtransmission/transmission.h | 4 +- macosx/PrefsController.mm | 2 +- 12 files changed, 363 insertions(+), 356 deletions(-) rename libtransmission/{natpmp.cc => port-forwarding-natpmp.cc} (62%) rename libtransmission/{natpmp_local.h => port-forwarding-natpmp.h} (64%) rename libtransmission/{upnp.cc => port-forwarding-upnp.cc} (82%) rename libtransmission/{upnp.h => port-forwarding-upnp.h} (66%) diff --git a/Transmission.xcodeproj/project.pbxproj b/Transmission.xcodeproj/project.pbxproj index 493e409c7..d1bbfb752 100644 --- a/Transmission.xcodeproj/project.pbxproj +++ b/Transmission.xcodeproj/project.pbxproj @@ -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 = ""; }; A2ED7D8D0CEF431B00970975 /* FilterButton.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FilterButton.h; sourceTree = ""; }; A2ED7D8E0CEF431B00970975 /* FilterButton.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FilterButton.mm; sourceTree = ""; }; - A2EE726E14DCCC950093C99A /* natpmp_local.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = natpmp_local.h; sourceTree = ""; }; + A2EE726E14DCCC950093C99A /* port-forwarding-natpmp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = port-forwarding-natpmp.h; sourceTree = ""; }; 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 = ""; }; BEFC1DF10C07861A00B0BB3C /* utils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = ""; }; BEFC1DF20C07861A00B0BB3C /* utils.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = utils.cc; sourceTree = ""; }; - BEFC1DF30C07861A00B0BB3C /* upnp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = upnp.h; sourceTree = ""; }; - BEFC1DF40C07861A00B0BB3C /* upnp.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = upnp.cc; sourceTree = ""; }; + BEFC1DF30C07861A00B0BB3C /* port-forwarding-upnp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = port-forwarding-upnp.h; sourceTree = ""; }; + BEFC1DF40C07861A00B0BB3C /* port-forwarding-upnp.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = port-forwarding-upnp.cc; sourceTree = ""; }; BEFC1DF50C07861A00B0BB3C /* transmission.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = transmission.h; sourceTree = ""; }; BEFC1DF60C07861A00B0BB3C /* session.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = session.cc; sourceTree = ""; }; BEFC1DF90C07861A00B0BB3C /* torrent.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = torrent.cc; sourceTree = ""; }; @@ -1073,7 +1073,7 @@ BEFC1E030C07861A00B0BB3C /* platform.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = platform.cc; sourceTree = ""; }; BEFC1E0C0C07861A00B0BB3C /* net.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = net.h; sourceTree = ""; }; BEFC1E0D0C07861A00B0BB3C /* net.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = net.cc; sourceTree = ""; }; - BEFC1E0F0C07861A00B0BB3C /* natpmp.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = natpmp.cc; sourceTree = ""; }; + BEFC1E0F0C07861A00B0BB3C /* port-forwarding-natpmp.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = port-forwarding-natpmp.cc; sourceTree = ""; }; BEFC1E140C07861A00B0BB3C /* session.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = session.h; sourceTree = ""; }; BEFC1E150C07861A00B0BB3C /* inout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = inout.h; sourceTree = ""; }; BEFC1E160C07861A00B0BB3C /* inout.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = inout.cc; sourceTree = ""; }; @@ -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 */, diff --git a/libtransmission/CMakeLists.txt b/libtransmission/CMakeLists.txt index cbde6bb55..bbd69423a 100644 --- a/libtransmission/CMakeLists.txt +++ b/libtransmission/CMakeLists.txt @@ -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 diff --git a/libtransmission/natpmp.cc b/libtransmission/port-forwarding-natpmp.cc similarity index 62% rename from libtransmission/natpmp.cc rename to libtransmission/port-forwarding-natpmp.cc index 3ac2adf18..ca12643ac 100644 --- a/libtransmission/natpmp.cc +++ b/libtransmission/port-forwarding-natpmp.cc @@ -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{}; 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, {}, {} }; } } diff --git a/libtransmission/natpmp_local.h b/libtransmission/port-forwarding-natpmp.h similarity index 64% rename from libtransmission/natpmp_local.h rename to libtransmission/port-forwarding-natpmp.h index 91c437ace..aec0b7451 100644 --- a/libtransmission/natpmp_local.h +++ b/libtransmission/port-forwarding-natpmp.h @@ -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 // time_t #include -#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; diff --git a/libtransmission/upnp.cc b/libtransmission/port-forwarding-upnp.cc similarity index 82% rename from libtransmission/upnp.cc rename to libtransmission/port-forwarding-upnp.cc index c6df4f339..943d87f97 100644 --- a/libtransmission/upnp.cc +++ b/libtransmission/port-forwarding-upnp.cc @@ -22,42 +22,44 @@ #include #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 @@ -257,20 +262,20 @@ static bool isFutureReady(std::future 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{ 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; } } diff --git a/libtransmission/upnp.h b/libtransmission/port-forwarding-upnp.h similarity index 66% rename from libtransmission/upnp.h rename to libtransmission/port-forwarding-upnp.h index 5b167e2e1..37fd92068 100644 --- a/libtransmission/upnp.h +++ b/libtransmission/port-forwarding-upnp.h @@ -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); /* @} */ diff --git a/libtransmission/port-forwarding.cc b/libtransmission/port-forwarding.cc index a2d267661..47ec12f21 100644 --- a/libtransmission/port-forwarding.cc +++ b/libtransmission/port-forwarding.cc @@ -9,241 +9,232 @@ #include +#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 natpmp; + stopTimer(); + natPulse(false); + startTimer(); + } - std::unique_ptr 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(); + } + + 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 natpmp_; + + std::unique_ptr timer_; }; -/*** -**** -***/ - -static char const* getNatStateStr(int state) +std::unique_ptr 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(); - } - - 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(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(session); } diff --git a/libtransmission/port-forwarding.h b/libtransmission/port-forwarding.h index 6e13dc6c8..ebfc3f3bc 100644 --- a/libtransmission/port-forwarding.h +++ b/libtransmission/port-forwarding.h @@ -9,22 +9,24 @@ #error only libtransmission should #include this header. #endif -#include "net.h" // tr_port +#include // 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 create(tr_session&); +}; diff --git a/libtransmission/session.cc b/libtransmission/session.cc index 184e6efbe..4be95ffe1 100644 --- a/libtransmission/session.cc +++ b/libtransmission/session.cc @@ -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(); } /*** diff --git a/libtransmission/session.h b/libtransmission/session.h index 15b768252..de26c3522 100644 --- a/libtransmission/session.h +++ b/libtransmission/session.h @@ -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 port_forwarding_; std::unique_ptr cache; diff --git a/libtransmission/transmission.h b/libtransmission/transmission.h index d4fcf10e2..5cb5c6873 100644 --- a/libtransmission/transmission.h +++ b/libtransmission/transmission.h @@ -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 { diff --git a/macosx/PrefsController.mm b/macosx/PrefsController.mm index c4a489087..eef6f6ef0 100644 --- a/macosx/PrefsController.mm +++ b/macosx/PrefsController.mm @@ -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);