From c481f62121b3f020dc5ac8f9354515de50ff960b Mon Sep 17 00:00:00 2001 From: Fuzzbawls Date: Fri, 23 Apr 2021 00:03:32 -0700 Subject: [PATCH 01/19] refactor: Move port mapping code to its own module This commit does not change behavior. --- CMakeLists.txt | 1 + src/Makefile.am | 2 + src/init.cpp | 1 + src/mapport.cpp | 138 ++++++++++++++++++++++++++++++++++++++++ src/mapport.h | 20 ++++++ src/net.cpp | 115 --------------------------------- src/net.h | 9 --- src/qt/optionsmodel.cpp | 1 + 8 files changed, 163 insertions(+), 124 deletions(-) create mode 100644 src/mapport.cpp create mode 100644 src/mapport.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f661c7d3477..8dec48242735 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -195,6 +195,7 @@ set(SERVER_SOURCES ./src/interfaces/wallet.cpp ./src/dbwrapper.cpp ./src/legacy/validation_zerocoin_legacy.cpp + ./src/mapport.cpp ./src/merkleblock.cpp ./src/miner.cpp ./src/blockassembler.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 87564a4d964a..b11f9a8f4b61 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -216,6 +216,7 @@ BITCOIN_CORE_H = \ budget/budgetvote.h \ budget/finalizedbudget.h \ budget/finalizedbudgetvote.h \ + mapport.h \ memusage.h \ masternode.h \ masternode-payments.h \ @@ -343,6 +344,7 @@ libbitcoin_server_a_SOURCES = \ sapling/sapling_validation.cpp \ merkleblock.cpp \ blockassembler.cpp \ + mapport.cpp \ miner.cpp \ net.cpp \ net_processing.cpp \ diff --git a/src/init.cpp b/src/init.cpp index 47dd50e99bf2..2395662f2b93 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -29,6 +29,7 @@ #include "httprpc.h" #include "invalid.h" #include "key.h" +#include "mapport.h" #include "masternode-payments.h" #include "masternodeconfig.h" #include "masternodeman.h" diff --git a/src/mapport.cpp b/src/mapport.cpp new file mode 100644 index 000000000000..f25b5cb55717 --- /dev/null +++ b/src/mapport.cpp @@ -0,0 +1,138 @@ +// Copyright (c) 2011-2020 The Bitcoin Core developers +// Copyright (c) 2021 The PIVX developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#if defined(HAVE_CONFIG_H) +#include "config/pivx-config.h" +#endif + +#include "mapport.h" + +#include "clientversion.h" +#include "logging.h" +#include "net.h" +#include "netaddress.h" +#include "netbase.h" +#include "threadinterrupt.h" +#include "util/system.h" + +#ifdef USE_UPNP +#include +#include +#include +// The minimum supported miniUPnPc API version is set to 10. This keeps compatibility +// with Ubuntu 16.04 LTS and Debian 8 libminiupnpc-dev packages. +static_assert(MINIUPNPC_API_VERSION >= 10, "miniUPnPc API version >= 10 assumed"); +#endif + +#include +#include +#include +#include +#include + +#ifdef USE_UPNP +static CThreadInterrupt g_upnp_interrupt; +static std::thread g_upnp_thread; +void ThreadMapPort() +{ + std::string port = strprintf("%u", GetListenPort()); + const char* multicastif = 0; + const char* minissdpdpath = 0; + struct UPNPDev* devlist = 0; + char lanaddr[64]; + + int error = 0; +#if MINIUPNPC_API_VERSION < 14 + devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error); +#else + devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, 2, &error); +#endif + + struct UPNPUrls urls; + struct IGDdatas data; + int r; + + r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)); + if (r == 1) { + if (fDiscover) { + char externalIPAddress[40]; + r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress); + if (r != UPNPCOMMAND_SUCCESS) { + LogPrintf("UPnP: GetExternalIPAddress() returned %d\n", r); + } else { + if (externalIPAddress[0]) { + CNetAddr resolved; + if (LookupHost(externalIPAddress, resolved, false)) { + LogPrintf("UPnP: ExternalIPAddress = %s\n", resolved.ToString().c_str()); + AddLocal(resolved, LOCAL_UPNP); + } + } else { + LogPrintf("UPnP: GetExternalIPAddress failed.\n"); + } + } + } + + std::string strDesc = PACKAGE_NAME " " + FormatFullVersion(); + + do { + r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0"); + + if (r != UPNPCOMMAND_SUCCESS) { + LogPrintf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", port, port, lanaddr, r, strupnperror(r)); + } else { + LogPrintf("UPnP Port Mapping successful.\n"); + } + } while(g_upnp_interrupt.sleep_for(std::chrono::minutes(20))); + + r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0); + LogPrintf("UPNP_DeletePortMapping() returned: %d\n", r); + freeUPNPDevlist(devlist); devlist = nullptr; + FreeUPNPUrls(&urls); + } else { + LogPrintf("No valid UPnP IGDs found\n"); + freeUPNPDevlist(devlist); + devlist = 0; + if (r != 0) + FreeUPNPUrls(&urls); + } +} + +void StartMapPort() +{ + if (!g_upnp_thread.joinable()) { + assert(!g_upnp_interrupt); + g_upnp_thread = std::thread(std::bind(&TraceThread, "upnp", &ThreadMapPort)); + } +} + +void InterruptMapPort() +{ + if (g_upnp_thread.joinable()) { + g_upnp_interrupt(); + } +} + +void StopMapPort() +{ + if (g_upnp_thread.joinable()) { + g_upnp_thread.join(); + g_upnp_interrupt.reset(); + } +} + +#else +void StartMapPort() +{ + // Intentionally left blank. +} +void InterruptMapPort() +{ + // Intentionally left blank. +} +void StopMapPort() +{ + // Intentionally left blank. +} +#endif diff --git a/src/mapport.h b/src/mapport.h new file mode 100644 index 000000000000..3f4bda9eab80 --- /dev/null +++ b/src/mapport.h @@ -0,0 +1,20 @@ +// Copyright (c) 2011-2020 The Bitcoin Core developers +// Copyright (c) 2021 The PIVX developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef PIVX_MAPPORT_H +#define PIVX_MAPPORT_H + +/** -upnp default */ +#ifdef USE_UPNP +static const bool DEFAULT_UPNP = USE_UPNP; +#else +static const bool DEFAULT_UPNP = false; +#endif + +void StartMapPort(); +void InterruptMapPort(); +void StopMapPort(); + +#endif //PIVX_MAPPORT_H diff --git a/src/net.cpp b/src/net.cpp index d203c07bf382..27c2eff4bb9e 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -35,16 +35,6 @@ #include #endif -#ifdef USE_UPNP -#include -#include -#include -// The minimum supported miniUPnPc API version is set to 10. This keeps compatibility -// with Ubuntu 16.04 LTS and Debian 8 libminiupnpc-dev packages. -static_assert(MINIUPNPC_API_VERSION >= 10, "miniUPnPc API version >= 10 assumed"); -#endif - - #include // Dump addresses to peers.dat and banlist.dat every 15 minutes (900s) @@ -1357,111 +1347,6 @@ void CConnman::WakeMessageHandler() } -#ifdef USE_UPNP -static CThreadInterrupt g_upnp_interrupt; -static std::thread g_upnp_thread; -void ThreadMapPort() -{ - std::string port = strprintf("%u", GetListenPort()); - const char* multicastif = 0; - const char* minissdpdpath = 0; - struct UPNPDev* devlist = 0; - char lanaddr[64]; - - int error = 0; -#if MINIUPNPC_API_VERSION < 14 - devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error); -#else - devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, 2, &error); -#endif - - struct UPNPUrls urls; - struct IGDdatas data; - int r; - - r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)); - if (r == 1) { - if (fDiscover) { - char externalIPAddress[40]; - r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress); - if (r != UPNPCOMMAND_SUCCESS) { - LogPrintf("UPnP: GetExternalIPAddress() returned %d\n", r); - } else { - if (externalIPAddress[0]) { - CNetAddr resolved; - if (LookupHost(externalIPAddress, resolved, false)) { - LogPrintf("UPnP: ExternalIPAddress = %s\n", resolved.ToString().c_str()); - AddLocal(resolved, LOCAL_UPNP); - } - } else { - LogPrintf("UPnP: GetExternalIPAddress failed.\n"); - } - } - } - - std::string strDesc = PACKAGE_NAME " " + FormatFullVersion(); - - do { - r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0"); - - if (r != UPNPCOMMAND_SUCCESS) { - LogPrintf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", port, port, lanaddr, r, strupnperror(r)); - } else { - LogPrintf("UPnP Port Mapping successful.\n"); - } - } while(g_upnp_interrupt.sleep_for(std::chrono::minutes(20))); - - r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0); - LogPrintf("UPNP_DeletePortMapping() returned: %d\n", r); - freeUPNPDevlist(devlist); devlist = nullptr; - FreeUPNPUrls(&urls); - } else { - LogPrintf("No valid UPnP IGDs found\n"); - freeUPNPDevlist(devlist); - devlist = 0; - if (r != 0) - FreeUPNPUrls(&urls); - } -} - -void StartMapPort() -{ - if (!g_upnp_thread.joinable()) { - assert(!g_upnp_interrupt); - g_upnp_thread = std::thread(std::bind(&TraceThread, "upnp", &ThreadMapPort)); - } -} - -void InterruptMapPort() -{ - if (g_upnp_thread.joinable()) { - g_upnp_interrupt(); - } -} - -void StopMapPort() -{ - if (g_upnp_thread.joinable()) { - g_upnp_thread.join(); - g_upnp_interrupt.reset(); - } -} - -#else -void StartMapPort() -{ - // Intentionally left blank. -} -void InterruptMapPort() -{ - // Intentionally left blank. -} -void StopMapPort() -{ - // Intentionally left blank. -} -#endif - static std::string GetDNSHost(const CDNSSeedData& data, ServiceFlags* requiredServiceBits) { //use default host for non-filter-capable seeds or if we use the default service bits (NODE_NETWORK) diff --git a/src/net.h b/src/net.h index fa5f538fed70..2348fd04da71 100644 --- a/src/net.h +++ b/src/net.h @@ -61,12 +61,6 @@ static const unsigned int MAX_SUBVERSION_LENGTH = 256; static const int MAX_OUTBOUND_CONNECTIONS = 16; /** -listen default */ static const bool DEFAULT_LISTEN = true; -/** -upnp default */ -#ifdef USE_UPNP -static const bool DEFAULT_UPNP = USE_UPNP; -#else -static const bool DEFAULT_UPNP = false; -#endif /** The maximum number of entries in mapAskFor */ static const size_t MAPASKFOR_MAX_SZ = MAX_INV_SZ; /** The maximum number of entries in setAskFor (larger due to getdata latency)*/ @@ -389,9 +383,6 @@ class CConnman }; extern std::unique_ptr g_connman; void Discover(); -void StartMapPort(); -void InterruptMapPort(); -void StopMapPort(); unsigned short GetListenPort(); bool BindListenPort(const CService& bindAddr, std::string& strError, bool fWhitelisted = false); void CheckOffsetDisconnectedPeers(const CNetAddr& ip); diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 7f4d39da2702..4a0aabeed820 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -15,6 +15,7 @@ #include "amount.h" #include "init.h" +#include "mapport.h" #include "net.h" #include "netbase.h" #include "txdb.h" // for -dbcache defaults From 7532090bfdde208565dd0d2fb59c74ad8d336941 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 16 Feb 2020 06:37:46 -0800 Subject: [PATCH 02/19] refactor: Replace magic number with named constant --- src/mapport.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mapport.cpp b/src/mapport.cpp index f25b5cb55717..406c2e4a4fac 100644 --- a/src/mapport.cpp +++ b/src/mapport.cpp @@ -35,6 +35,9 @@ static_assert(MINIUPNPC_API_VERSION >= 10, "miniUPnPc API version >= 10 assumed" #ifdef USE_UPNP static CThreadInterrupt g_upnp_interrupt; static std::thread g_upnp_thread; + +static constexpr auto PORT_MAPPING_REANNOUNCE_PERIOD = std::chrono::minutes(20); + void ThreadMapPort() { std::string port = strprintf("%u", GetListenPort()); @@ -84,7 +87,7 @@ void ThreadMapPort() } else { LogPrintf("UPnP Port Mapping successful.\n"); } - } while(g_upnp_interrupt.sleep_for(std::chrono::minutes(20))); + } while(g_upnp_interrupt.sleep_for(PORT_MAPPING_REANNOUNCE_PERIOD)); r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0); LogPrintf("UPNP_DeletePortMapping() returned: %d\n", r); From d2fa5c4e15dcd0dc3682decaa7f7bda80ba9e9ff Mon Sep 17 00:00:00 2001 From: Fuzzbawls Date: Fri, 23 Apr 2021 00:26:00 -0700 Subject: [PATCH 03/19] Make ThreadMapPort static --- src/mapport.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mapport.cpp b/src/mapport.cpp index 406c2e4a4fac..9d0b257f6654 100644 --- a/src/mapport.cpp +++ b/src/mapport.cpp @@ -38,7 +38,7 @@ static std::thread g_upnp_thread; static constexpr auto PORT_MAPPING_REANNOUNCE_PERIOD = std::chrono::minutes(20); -void ThreadMapPort() +static void ThreadMapPort() { std::string port = strprintf("%u", GetListenPort()); const char* multicastif = 0; From 2abea67a775595ad5f20dbc624857aff2d7a066f Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Tue, 18 Feb 2020 23:23:30 +0200 Subject: [PATCH 04/19] net: Keep trying to use UPnP when -upnp=1 # Conflicts: # src/mapport.cpp --- src/mapport.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/mapport.cpp b/src/mapport.cpp index 9d0b257f6654..384d20247249 100644 --- a/src/mapport.cpp +++ b/src/mapport.cpp @@ -37,9 +37,11 @@ static CThreadInterrupt g_upnp_interrupt; static std::thread g_upnp_thread; static constexpr auto PORT_MAPPING_REANNOUNCE_PERIOD = std::chrono::minutes(20); +static constexpr auto PORT_MAPPING_RETRY_PERIOD = std::chrono::minutes(5); -static void ThreadMapPort() +static bool ProcessUpnp() { + bool ret = false; std::string port = strprintf("%u", GetListenPort()); const char* multicastif = 0; const char* minissdpdpath = 0; @@ -83,11 +85,15 @@ static void ThreadMapPort() r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0"); if (r != UPNPCOMMAND_SUCCESS) { + ret = false; LogPrintf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", port, port, lanaddr, r, strupnperror(r)); + break; } else { + ret = true; LogPrintf("UPnP Port Mapping successful.\n"); } - } while(g_upnp_interrupt.sleep_for(PORT_MAPPING_REANNOUNCE_PERIOD)); + } while (g_upnp_interrupt.sleep_for(PORT_MAPPING_REANNOUNCE_PERIOD)); + g_upnp_interrupt.reset(); r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0); LogPrintf("UPNP_DeletePortMapping() returned: %d\n", r); @@ -100,6 +106,15 @@ static void ThreadMapPort() if (r != 0) FreeUPNPUrls(&urls); } + + return ret; +} + +static void ThreadMapPort() +{ + do { + if (ProcessUpnp()) return; + } while (g_upnp_interrupt.sleep_for(PORT_MAPPING_RETRY_PERIOD)); } void StartMapPort() From 06dc0dde776fbad807f02af6a562bb48a4da3fbb Mon Sep 17 00:00:00 2001 From: Fuzzbawls Date: Fri, 23 Apr 2021 00:32:59 -0700 Subject: [PATCH 05/19] net: Add flags for port mapping protocols --- src/init.cpp | 4 +--- src/mapport.cpp | 31 +++++++++++++++++++++++++++++-- src/mapport.h | 7 ++++++- src/qt/optionsmodel.cpp | 7 +------ 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 2395662f2b93..522869340f1b 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1940,9 +1940,7 @@ bool AppInitMain() Discover(); // Map ports with UPnP - if (gArgs.GetBoolArg("-upnp", DEFAULT_UPNP)) { - StartMapPort(); - } + StartMapPort(gArgs.GetBoolArg("-upnp", DEFAULT_UPNP)); std::string strNodeError; CConnman::Options connOptions; diff --git a/src/mapport.cpp b/src/mapport.cpp index 384d20247249..c519a9f5c969 100644 --- a/src/mapport.cpp +++ b/src/mapport.cpp @@ -26,6 +26,7 @@ static_assert(MINIUPNPC_API_VERSION >= 10, "miniUPnPc API version >= 10 assumed"); #endif +#include #include #include #include @@ -35,6 +36,7 @@ static_assert(MINIUPNPC_API_VERSION >= 10, "miniUPnPc API version >= 10 assumed" #ifdef USE_UPNP static CThreadInterrupt g_upnp_interrupt; static std::thread g_upnp_thread; +static std::atomic_uint g_mapport_target_proto{MapPortProtoFlag::NONE}; static constexpr auto PORT_MAPPING_REANNOUNCE_PERIOD = std::chrono::minutes(20); static constexpr auto PORT_MAPPING_RETRY_PERIOD = std::chrono::minutes(5); @@ -117,7 +119,7 @@ static void ThreadMapPort() } while (g_upnp_interrupt.sleep_for(PORT_MAPPING_RETRY_PERIOD)); } -void StartMapPort() +void StartThreadMapPort() { if (!g_upnp_thread.joinable()) { assert(!g_upnp_interrupt); @@ -125,6 +127,31 @@ void StartMapPort() } } +static void DispatchMapPort() +{ + if (g_mapport_target_proto == MapPortProtoFlag::UPNP) { + StartThreadMapPort(); + } else { + InterruptMapPort(); + StopMapPort(); + } +} + +static void MapPortProtoSetEnabled(MapPortProtoFlag proto, bool enabled) +{ + if (enabled) { + g_mapport_target_proto |= proto; + } else { + g_mapport_target_proto &= ~proto; + } +} + +void StartMapPort(bool use_upnp) +{ + MapPortProtoSetEnabled(MapPortProtoFlag::UPNP, use_upnp); + DispatchMapPort(); +} + void InterruptMapPort() { if (g_upnp_thread.joinable()) { @@ -141,7 +168,7 @@ void StopMapPort() } #else -void StartMapPort() +void StartMapPort(bool use_upnp) { // Intentionally left blank. } diff --git a/src/mapport.h b/src/mapport.h index 3f4bda9eab80..329f35f67230 100644 --- a/src/mapport.h +++ b/src/mapport.h @@ -13,7 +13,12 @@ static const bool DEFAULT_UPNP = USE_UPNP; static const bool DEFAULT_UPNP = false; #endif -void StartMapPort(); +enum MapPortProtoFlag : unsigned int { + NONE = 0x00, + UPNP = 0x01, +}; + +void StartMapPort(bool use_upnp); void InterruptMapPort(); void StopMapPort(); diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 4a0aabeed820..fba8bdd60e68 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -309,12 +309,7 @@ bool OptionsModel::setData(const QModelIndex& index, const QVariant& value, int break; case MapPortUPnP: // core option - can be changed on-the-fly settings.setValue("fUseUPnP", value.toBool()); - if (value.toBool()) { - StartMapPort(); - } else { - InterruptMapPort(); - StopMapPort(); - } + StartMapPort(value.toBool()); break; case MinimizeOnClose: fMinimizeOnClose = value.toBool(); From 266d322d925adf2dadfa92db0952ad8a3c5c3545 Mon Sep 17 00:00:00 2001 From: Fuzzbawls Date: Fri, 23 Apr 2021 00:45:55 -0700 Subject: [PATCH 06/19] scripted-diff: Rename UPnP stuff -BEGIN VERIFY SCRIPT- sed -i 's/g_upnp_interrupt/g_mapport_interrupt/' src/mapport.cpp sed -i 's/g_upnp_thread/g_mapport_thread/' src/mapport.cpp sed -i 's/LOCAL_UPNP/LOCAL_MAPPED/' src/mapport.cpp sed -i 's/\bupnp\b/mapport/' src/mapport.cpp sed -i 's/LOCAL_UPNP, /LOCAL_MAPPED,/' src/net.h -END VERIFY SCRIPT- --- src/mapport.cpp | 28 ++++++++++++++-------------- src/net.h | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/mapport.cpp b/src/mapport.cpp index c519a9f5c969..fcf957631712 100644 --- a/src/mapport.cpp +++ b/src/mapport.cpp @@ -34,8 +34,8 @@ static_assert(MINIUPNPC_API_VERSION >= 10, "miniUPnPc API version >= 10 assumed" #include #ifdef USE_UPNP -static CThreadInterrupt g_upnp_interrupt; -static std::thread g_upnp_thread; +static CThreadInterrupt g_mapport_interrupt; +static std::thread g_mapport_thread; static std::atomic_uint g_mapport_target_proto{MapPortProtoFlag::NONE}; static constexpr auto PORT_MAPPING_REANNOUNCE_PERIOD = std::chrono::minutes(20); @@ -73,7 +73,7 @@ static bool ProcessUpnp() CNetAddr resolved; if (LookupHost(externalIPAddress, resolved, false)) { LogPrintf("UPnP: ExternalIPAddress = %s\n", resolved.ToString().c_str()); - AddLocal(resolved, LOCAL_UPNP); + AddLocal(resolved, LOCAL_MAPPED); } } else { LogPrintf("UPnP: GetExternalIPAddress failed.\n"); @@ -94,8 +94,8 @@ static bool ProcessUpnp() ret = true; LogPrintf("UPnP Port Mapping successful.\n"); } - } while (g_upnp_interrupt.sleep_for(PORT_MAPPING_REANNOUNCE_PERIOD)); - g_upnp_interrupt.reset(); + } while (g_mapport_interrupt.sleep_for(PORT_MAPPING_REANNOUNCE_PERIOD)); + g_mapport_interrupt.reset(); r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0); LogPrintf("UPNP_DeletePortMapping() returned: %d\n", r); @@ -116,14 +116,14 @@ static void ThreadMapPort() { do { if (ProcessUpnp()) return; - } while (g_upnp_interrupt.sleep_for(PORT_MAPPING_RETRY_PERIOD)); + } while (g_mapport_interrupt.sleep_for(PORT_MAPPING_RETRY_PERIOD)); } void StartThreadMapPort() { - if (!g_upnp_thread.joinable()) { - assert(!g_upnp_interrupt); - g_upnp_thread = std::thread(std::bind(&TraceThread, "upnp", &ThreadMapPort)); + if (!g_mapport_thread.joinable()) { + assert(!g_mapport_interrupt); + g_mapport_thread = std::thread(std::bind(&TraceThread, "mapport", &ThreadMapPort)); } } @@ -154,16 +154,16 @@ void StartMapPort(bool use_upnp) void InterruptMapPort() { - if (g_upnp_thread.joinable()) { - g_upnp_interrupt(); + if (g_mapport_thread.joinable()) { + g_mapport_interrupt(); } } void StopMapPort() { - if (g_upnp_thread.joinable()) { - g_upnp_thread.join(); - g_upnp_interrupt.reset(); + if (g_mapport_thread.joinable()) { + g_mapport_thread.join(); + g_mapport_interrupt.reset(); } } diff --git a/src/net.h b/src/net.h index 2348fd04da71..e4ed7345d2d9 100644 --- a/src/net.h +++ b/src/net.h @@ -418,7 +418,7 @@ enum { LOCAL_NONE, // unknown LOCAL_IF, // address a local interface listens on LOCAL_BIND, // address explicit bound to - LOCAL_UPNP, // address reported by UPnP + LOCAL_MAPPED, // address reported by UPnP LOCAL_MANUAL, // address explicitly specified (-externalip=) LOCAL_MAX From faed148cb8aba62bb0e65d89f59b53a0655ba9f9 Mon Sep 17 00:00:00 2001 From: Fuzzbawls Date: Fri, 23 Apr 2021 01:41:10 -0700 Subject: [PATCH 07/19] gui: Apply port mapping changes on save This commit does not change behavior. It is a prerequisite for NAT-PMP support adding. --- src/qt/clientmodel.h | 4 ++++ src/qt/optionsmodel.cpp | 1 - src/qt/pivx/settings/settingswalletoptionswidget.cpp | 4 ++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index f783aaecd931..6e32d8891024 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -9,6 +9,8 @@ #include "uint256.h" #include "chain.h" +#include "mapport.h" + #include #include @@ -94,6 +96,8 @@ class ClientModel : public QObject bool getTorInfo(std::string& ip_port) const; + static void mapPort(bool use_upnp) { StartMapPort(use_upnp); } + // Start/Stop the masternode polling timer void startMasternodesTimer(); void stopMasternodesTimer(); diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index fba8bdd60e68..b8674b92be58 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -309,7 +309,6 @@ bool OptionsModel::setData(const QModelIndex& index, const QVariant& value, int break; case MapPortUPnP: // core option - can be changed on-the-fly settings.setValue("fUseUPnP", value.toBool()); - StartMapPort(value.toBool()); break; case MinimizeOnClose: fMinimizeOnClose = value.toBool(); diff --git a/src/qt/pivx/settings/settingswalletoptionswidget.cpp b/src/qt/pivx/settings/settingswalletoptionswidget.cpp index 26a61951c170..eebb9a5ba60f 100644 --- a/src/qt/pivx/settings/settingswalletoptionswidget.cpp +++ b/src/qt/pivx/settings/settingswalletoptionswidget.cpp @@ -55,6 +55,10 @@ SettingsWalletOptionsWidget::SettingsWalletOptionsWidget(PIVXGUI* _window, QWidg connect(ui->pushButtonSave, &QPushButton::clicked, [this] { Q_EMIT saveSettings(); }); connect(ui->pushButtonReset, &QPushButton::clicked, this, &SettingsWalletOptionsWidget::onResetClicked); connect(ui->pushButtonClean, &QPushButton::clicked, [this] { Q_EMIT discardSettings(); }); + + connect(ui->pushButtonSave, &QPushButton::clicked, [this](){ + ClientModel::mapPort(ui->checkBoxMap->isChecked()); + }); } void SettingsWalletOptionsWidget::onResetClicked() From 84cd1184c1a656fc6c8edb80e9eb44adf6d64ba7 Mon Sep 17 00:00:00 2001 From: Fuzzbawls Date: Fri, 23 Apr 2021 02:41:21 -0700 Subject: [PATCH 08/19] net: Add initial libnatpmp support --- .github/workflows/build-and-test.yml | 2 +- CMakeLists.txt | 5 ++ configure.ac | 47 +++++++++++ contrib/cmake/FindNAT-PMP.cmake | 40 ++++++++++ depends/Makefile | 6 +- depends/config.site.in | 4 + depends/packages/libnatpmp.mk | 19 +++++ depends/packages/packages.mk | 1 + src/Makefile.am | 2 +- src/Makefile.bench.include | 2 +- src/Makefile.qt.include | 2 +- src/Makefile.qttest.include | 2 +- src/Makefile.test.include | 2 +- src/mapport.cpp | 114 ++++++++++++++++++++++++++- src/mapport.h | 1 + src/net.h | 2 +- src/qt/CMakeLists.txt | 4 + src/test/CMakeLists.txt | 4 + 18 files changed, 247 insertions(+), 12 deletions(-) create mode 100644 contrib/cmake/FindNAT-PMP.cmake create mode 100644 depends/packages/libnatpmp.mk diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index ecba1bb5db19..548e70920380 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -165,7 +165,7 @@ jobs: os: ubuntu-18.04 host: x86_64-unknown-linux-gnu apt_get: python3-zmq qtbase5-dev qttools5-dev-tools libqt5svg5-dev libqt5charts5-dev libqrencode-dev libdbus-1-dev libharfbuzz-dev - dep_opts: NO_QT=1 NO_UPNP=1 DEBUG=1 ALLOW_HOST_PACKAGES=1 + dep_opts: NO_QT=1 NO_UPNP=1 NO_NATPMP=1 DEBUG=1 ALLOW_HOST_PACKAGES=1 - name: macOS 10.12 os: ubuntu-18.04 diff --git a/CMakeLists.txt b/CMakeLists.txt index 8dec48242735..cff73d1a9638 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,6 +79,7 @@ find_package(GMP REQUIRED) find_package(ZMQ) find_package(Miniupnp) +find_package(NAT-PMP) find_package(Boost COMPONENTS system filesystem thread REQUIRED) find_package(Sodium REQUIRED) @@ -560,6 +561,10 @@ if(MINIUPNP_FOUND) target_link_libraries(pivxd ${MINIUPNP_LIBRARY}) target_include_directories(pivxd PUBLIC ${MINIUPNP_INCLUDE_DIR}) endif() +if(NAT-PMP_FOUND) + target_link_libraries(pivxd ${NAT-PMP_LIBRARY}) + target_include_directories(pivxd PUBLIC ${NAT-PMP_INCLUDE_DIR}) +endif() if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(pivxd "-framework Cocoa") diff --git a/configure.ac b/configure.ac index 31675dd059dc..2f96ea51cf55 100644 --- a/configure.ac +++ b/configure.ac @@ -146,6 +146,18 @@ AC_ARG_ENABLE([upnp-default], [use_upnp_default=$enableval], [use_upnp_default=no]) +AC_ARG_WITH([natpmp], + [AS_HELP_STRING([--with-natpmp], + [enable NAT-PMP (default is yes if libnatpmp is found)])], + [use_natpmp=$withval], + [use_natpmp=auto]) + +AC_ARG_ENABLE([natpmp-default], + [AS_HELP_STRING([--enable-natpmp-default], + [if NAT-PMP is enabled, turn it on at startup (default is no)])], + [use_natpmp_default=$enableval], + [use_natpmp_default=no]) + AC_ARG_ENABLE(tests, AS_HELP_STRING([--disable-tests],[do not compile tests (default is to compile)]), [use_tests=$enableval], @@ -1011,6 +1023,7 @@ if test "x$enable_fuzz" = "xyes"; then enable_wallet=yes # needs to be built for now. use_bench=no use_upnp=no + use_natpmp=no use_zmq=no else BITCOIN_QT_INIT @@ -1053,6 +1066,13 @@ if test x$have_miniupnpc != xno; then fi fi +dnl Check for libnatpmp (optional). +if test "x$use_natpmp" != xno; then + AC_CHECK_HEADERS([natpmp.h], + [AC_CHECK_LIB([natpmp], [initnatpmp], [NATPMP_LIBS=-lnatpmp], [have_natpmp=no])], + [have_natpmp=no]) +fi + if test x$build_bitcoin_utils$build_bitcoind$bitcoin_enable_qt$use_tests$use_bench = xnonononono; then use_boost=no else @@ -1358,6 +1378,31 @@ else fi fi +dnl Enable NAT-PMP support. +AC_MSG_CHECKING([whether to build with support for NAT-PMP]) +if test "x$have_natpmp" = xno; then + if test "x$use_natpmp" = xyes; then + AC_MSG_ERROR([NAT-PMP requested but cannot be built. Use --without-natpmp]) + fi + AC_MSG_RESULT([no]) + use_natpmp=no +else + if test "x$use_natpmp" != xno; then + AC_MSG_RESULT([yes]) + AC_MSG_CHECKING([whether to build with NAT-PMP enabled by default]) + use_natpmp=yes + natpmp_setting=0 + if test "x$use_natpmp_default" != xno; then + use_natpmp_default=yes + natpmp_setting=1 + fi + AC_MSG_RESULT($use_natpmp_default) + AC_DEFINE_UNQUOTED([USE_NATPMP], [$natpmp_setting], [NAT-PMP support not compiled if undefined, otherwise value (0 or 1) determines default state]) + else + AC_MSG_RESULT([no]) + fi +fi + dnl these are only used when qt is enabled BUILD_TEST_QT="" if test x$bitcoin_enable_qt != xno; then @@ -1492,6 +1537,7 @@ AC_SUBST(BOOST_LIBS) AC_SUBST(TESTDEFS) AC_SUBST(MINIUPNPC_CPPFLAGS) AC_SUBST(MINIUPNPC_LIBS) +AC_SUBST(NATPMP_LIBS) AC_SUBST(EVENT_LIBS) AC_SUBST(EVENT_PTHREADS_LIBS) AC_SUBST(SODIUM_LIBS) @@ -1580,6 +1626,7 @@ if test x$use_tests != xno; then fi echo " with bench = $use_bench" echo " with upnp = $use_upnp" +echo " with natpmp = $use_natpmp" echo " with params = $params_path" echo " use asm = $use_asm" echo " sanitizers = $use_sanitizers" diff --git a/contrib/cmake/FindNAT-PMP.cmake b/contrib/cmake/FindNAT-PMP.cmake new file mode 100644 index 000000000000..98ada739a03c --- /dev/null +++ b/contrib/cmake/FindNAT-PMP.cmake @@ -0,0 +1,40 @@ +# - Find NAT-PMP +# This module defines +# NAT-PMP_INCLUDE_DIR, where to find NAT-PMP headers +# NAT-PMP_LIBRARY, NAT-PMP libraries +# NAT-PMP_FOUND, If false, do not try to use NAT-PMP + +set(NAT-PMP_PREFIX "" CACHE PATH "path ") + +find_path(NAT-PMP_INCLUDE_DIR natpmp.h + PATHS ${NAT-PMP_PREFIX}/include /usr/include /usr/local/include) + +find_library(NAT-PMP_LIBRARY NAMES natpmp libnatpmp + PATHS ${NAT-PMP_PREFIX}/lib /usr/lib /usr/local/lib) + +if(NAT-PMP_INCLUDE_DIR AND NAT-PMP_LIBRARY) + get_filename_component(NAT-PMP_LIBRARY_DIR ${NAT-PMP_LIBRARY} PATH) + set(NAT-PMP_FOUND TRUE) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + NAT-PMP DEFAULT_MSG + NAT-PMP_INCLUDE_DIR + NAT-PMP_LIBRARY +) + +if(NAT-PMP_FOUND) + if(NOT NAT-PMP_FIND_QUIETLY) + MESSAGE(STATUS "Found NAT-PMP: ${NAT-PMP_LIBRARY}") + endif() +else() + if(NAT-PMP_FIND_REQUIRED) + message(FATAL_ERROR "Could not find NAT-PMP") + endif() +endif() + +mark_as_advanced( + NAT-PMP_LIBRARY + NAT-PMP_INCLUDE_DIR +) \ No newline at end of file diff --git a/depends/Makefile b/depends/Makefile index ba86d937f344..5a39ec94ae31 100644 --- a/depends/Makefile +++ b/depends/Makefile @@ -36,6 +36,7 @@ NO_QT ?= NO_WALLET ?= NO_ZMQ ?= NO_UPNP ?= +NO_NATPMP ?= NO_RUST ?= FALLBACK_DOWNLOAD_PATH ?= https://depends.pivx.org @@ -130,9 +131,11 @@ endif qt_packages_$(NO_QT) = $(qt_packages) $(qt_$(host_os)_packages) $(qt_$(host_arch)_$(host_os)_packages) wallet_packages_$(NO_WALLET) = $(wallet_packages) upnp_packages_$(NO_UPNP) = $(upnp_packages) +natpmp_packages_$(NO_NATPMP) = $(natpmp_packages) + zmq_packages_$(NO_ZMQ) = $(zmq_packages) -packages += $($(host_arch)_$(host_os)_packages) $($(host_os)_packages) $(qt_packages_) $(rust_packages) $(wallet_packages_) $(upnp_packages_) +packages += $($(host_arch)_$(host_os)_packages) $($(host_os)_packages) $(qt_packages_) $(rust_packages) $(wallet_packages_) $(upnp_packages_) $(natpmp_packages_) native_packages += $($(host_arch)_$(host_os)_native_packages) $($(host_os)_native_packages) ifneq ($(qt_packages_),) @@ -189,6 +192,7 @@ $(host_prefix)/share/config.site : config.site.in $(host_prefix)/.stamp_$(final_ -e 's|@no_zmq@|$(NO_ZMQ)|' \ -e 's|@no_wallet@|$(NO_WALLET)|' \ -e 's|@no_upnp@|$(NO_UPNP)|' \ + -e 's|@no_natpmp@|$(NO_NATPMP)|' \ -e 's|@debug@|$(DEBUG)|' \ $< > $@ $(AT)touch $@ diff --git a/depends/config.site.in b/depends/config.site.in index ade83626560d..cb680237b167 100644 --- a/depends/config.site.in +++ b/depends/config.site.in @@ -28,6 +28,10 @@ if test -z $with_miniupnpc && test -n "@no_upnp@"; then with_miniupnpc=no fi +if test -z $with_natpmp && test -n "@no_natpmp@"; then + with_natpmp=no +fi + if test -z $with_gui && test -n "@no_qt@"; then with_gui=no fi diff --git a/depends/packages/libnatpmp.mk b/depends/packages/libnatpmp.mk new file mode 100644 index 000000000000..a24f201859a0 --- /dev/null +++ b/depends/packages/libnatpmp.mk @@ -0,0 +1,19 @@ +package=libnatpmp +$(package)_version=20150609 +$(package)_download_path=https://miniupnp.tuxfamily.org/files/ +$(package)_file_name=$(package)-$($(package)_version).tar.gz +$(package)_sha256_hash=e1aa9c4c4219bc06943d6b2130f664daee213fb262fcb94dd355815b8f4536b0 + +define $(package)_set_vars + $(package)_build_opts=CC="$($(package)_cc)" +endef + +define $(package)_build_cmds + $(MAKE) libnatpmp.a $($(package)_build_opts) +endef + +define $(package)_stage_cmds + mkdir -p $($(package)_staging_prefix_dir)/include $($(package)_staging_prefix_dir)/lib &&\ + install *.h $($(package)_staging_prefix_dir)/include &&\ + install libnatpmp.a $($(package)_staging_prefix_dir)/lib +endef diff --git a/depends/packages/packages.mk b/depends/packages/packages.mk index 41349501135c..8a3a63a1b790 100644 --- a/depends/packages/packages.mk +++ b/depends/packages/packages.mk @@ -86,6 +86,7 @@ wallet_packages=bdb zmq_packages=zeromq upnp_packages=miniupnpc +natpmp_packages=libnatpmp darwin_native_packages = native_ds_store native_mac_alias diff --git a/src/Makefile.am b/src/Makefile.am index b11f9a8f4b61..f9d0ee976cbd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -627,7 +627,7 @@ pivxd_LDADD = \ $(LIBRUSTZCASH) \ $(LIBZCASH_LIBS) -pivxd_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS) +pivxd_LDADD += $(BOOST_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(ZMQ_LIBS) # pivx-cli binary # pivx_cli_SOURCES = pivx-cli.cpp diff --git a/src/Makefile.bench.include b/src/Makefile.bench.include index 80c81c30276b..9b7d1855ceec 100644 --- a/src/Makefile.bench.include +++ b/src/Makefile.bench.include @@ -47,7 +47,7 @@ if ENABLE_ZMQ bench_bench_pivx_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) endif -bench_bench_pivx_LDADD += $(LIBBITCOIN_CONSENSUS) $(BOOST_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) +bench_bench_pivx_LDADD += $(LIBBITCOIN_CONSENSUS) $(BOOST_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) bench_bench_pivx_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) # !TODO: .raw.h generated test files are not removed with make clean diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 0c0e91983ae3..d8f6e1a899ec 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -646,7 +646,7 @@ if ENABLE_ZMQ qt_pivx_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) endif qt_pivx_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBBITCOIN_ZEROCOIN) $(LIBSAPLING) $(LIBRUSTZCASH) $(LIBZCASH_LIBS) $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) \ - $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(SVG_LIBS) $(CHARTS_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \ + $(BOOST_LIBS) $(QT_LIBS) $(QT_DBUS_LIBS) $(QR_LIBS) $(SVG_LIBS) $(CHARTS_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(LIBSECP256K1) \ $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) qt_pivx_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) qt_pivx_qt_LIBTOOLFLAGS = $(AM_LIBTOOLFLAGS) --tag CXX diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include index b80ec1fa5e6a..fe2be2add0c8 100644 --- a/src/Makefile.qttest.include +++ b/src/Makefile.qttest.include @@ -28,7 +28,7 @@ qt_test_test_pivx_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) endif qt_test_test_pivx_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBBITCOIN_ZEROCOIN) $(LIBLEVELDB) $(LIBSAPLING) $(LIBRUSTZCASH) $(LIBZCASH_LIBS) \ $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \ - $(QR_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) \ + $(QR_LIBS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(LIBSECP256K1) \ $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) qt_test_test_pivx_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) qt_test_test_pivx_qt_CXXFLAGS = $(AM_CXXFLAGS) $(QT_PIE_FLAGS) diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 6123d0918fd6..4f6b78c02eaa 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -185,7 +185,7 @@ test_test_pivx_LDADD += $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMM test_test_pivx_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) -test_test_pivx_LDADD += $(LIBRUSTZCASH) $(LIBBITCOIN_CONSENSUS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(LIBZCASH_LIBS) +test_test_pivx_LDADD += $(LIBRUSTZCASH) $(LIBBITCOIN_CONSENSUS) $(BDB_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(LIBZCASH_LIBS) test_test_pivx_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static if ENABLE_ZMQ diff --git a/src/mapport.cpp b/src/mapport.cpp index fcf957631712..e023e2068bcd 100644 --- a/src/mapport.cpp +++ b/src/mapport.cpp @@ -17,6 +17,11 @@ #include "threadinterrupt.h" #include "util/system.h" +#ifdef USE_NATPMP +#include +#include +#endif // USE_NATPMP + #ifdef USE_UPNP #include #include @@ -24,7 +29,7 @@ // The minimum supported miniUPnPc API version is set to 10. This keeps compatibility // with Ubuntu 16.04 LTS and Debian 8 libminiupnpc-dev packages. static_assert(MINIUPNPC_API_VERSION >= 10, "miniUPnPc API version >= 10 assumed"); -#endif +#endif // USE_UPNP #include #include @@ -33,7 +38,7 @@ static_assert(MINIUPNPC_API_VERSION >= 10, "miniUPnPc API version >= 10 assumed" #include #include -#ifdef USE_UPNP +#if defined(USE_NATPMP) || defined(USE_UPNP) static CThreadInterrupt g_mapport_interrupt; static std::thread g_mapport_thread; static std::atomic_uint g_mapport_target_proto{MapPortProtoFlag::NONE}; @@ -41,6 +46,106 @@ static std::atomic_uint g_mapport_target_proto{MapPortProtoFlag::NONE}; static constexpr auto PORT_MAPPING_REANNOUNCE_PERIOD = std::chrono::minutes(20); static constexpr auto PORT_MAPPING_RETRY_PERIOD = std::chrono::minutes(5); +#ifdef USE_NATPMP +static uint16_t g_mapport_external_port = 0; +static bool NatpmpInit(natpmp_t* natpmp) +{ + const int r_init = initnatpmp(natpmp, /* detect gateway automatically */ 0, /* forced gateway - NOT APPLIED*/ 0); + if (r_init == 0) return true; + LogPrintf("natpmp: initnatpmp() failed with %d error.\n", r_init); + return false; +} + +static bool NatpmpDiscover(natpmp_t* natpmp, struct in_addr& external_ipv4_addr) +{ + const int r_send = sendpublicaddressrequest(natpmp); + if (r_send == 2 /* OK */) { + int r_read; + natpmpresp_t response; + do { + r_read = readnatpmpresponseorretry(natpmp, &response); + } while (r_read == NATPMP_TRYAGAIN); + + if (r_read == 0) { + external_ipv4_addr = response.pnu.publicaddress.addr; + return true; + } else if (r_read == NATPMP_ERR_NOGATEWAYSUPPORT) { + LogPrintf("natpmp: The gateway does not support NAT-PMP.\n"); + } else { + LogPrintf("natpmp: readnatpmpresponseorretry() for public address failed with %d error.\n", r_read); + } + } else { + LogPrintf("natpmp: sendpublicaddressrequest() failed with %d error.\n", r_send); + } + + return false; +} + +static bool NatpmpMapping(natpmp_t* natpmp, const struct in_addr& external_ipv4_addr, uint16_t private_port, bool& external_ip_discovered) +{ + const uint16_t suggested_external_port = g_mapport_external_port ? g_mapport_external_port : private_port; + const int r_send = sendnewportmappingrequest(natpmp, NATPMP_PROTOCOL_TCP, private_port, suggested_external_port, 3600 /*seconds*/); + if (r_send == 12 /* OK */) { + int r_read; + natpmpresp_t response; + do { + r_read = readnatpmpresponseorretry(natpmp, &response); + } while (r_read == NATPMP_TRYAGAIN); + + if (r_read == 0) { + auto pm = response.pnu.newportmapping; + if (private_port == pm.privateport && pm.lifetime > 0) { + g_mapport_external_port = pm.mappedpublicport; + const CService external{external_ipv4_addr, pm.mappedpublicport}; + if (!external_ip_discovered && fDiscover) { + AddLocal(external, LOCAL_MAPPED); + external_ip_discovered = true; + } + LogPrintf("natpmp: Port mapping successful. External address = %s\n", external.ToString()); + return true; + } else { + LogPrintf("natpmp: Port mapping failed.\n"); + } + } else if (r_read == NATPMP_ERR_NOGATEWAYSUPPORT) { + LogPrintf("natpmp: The gateway does not support NAT-PMP.\n"); + } else { + LogPrintf("natpmp: readnatpmpresponseorretry() for port mapping failed with %d error.\n", r_read); + } + } else { + LogPrintf("natpmp: sendnewportmappingrequest() failed with %d error.\n", r_send); + } + + return false; +} + +static bool ProcessNatpmp() +{ + bool ret = false; + natpmp_t natpmp; + struct in_addr external_ipv4_addr; + if (NatpmpInit(&natpmp) && NatpmpDiscover(&natpmp, external_ipv4_addr)) { + bool external_ip_discovered = false; + const uint16_t private_port = GetListenPort(); + do { + ret = NatpmpMapping(&natpmp, external_ipv4_addr, private_port, external_ip_discovered); + } while (ret && g_mapport_interrupt.sleep_for(PORT_MAPPING_REANNOUNCE_PERIOD)); + g_mapport_interrupt.reset(); + + const int r_send = sendnewportmappingrequest(&natpmp, NATPMP_PROTOCOL_TCP, private_port, g_mapport_external_port, /* remove a port mapping */ 0); + g_mapport_external_port = 0; + if (r_send == 12 /* OK */) { + LogPrintf("natpmp: Port mapping removed successfully.\n"); + } else { + LogPrintf("natpmp: sendnewportmappingrequest(0) failed with %d error.\n", r_send); + } + } + + closenatpmp(&natpmp); + return ret; +} +#endif // USE_NATPMP + +#ifdef USE_UPNP static bool ProcessUpnp() { bool ret = false; @@ -111,6 +216,7 @@ static bool ProcessUpnp() return ret; } +#endif // USE_UPNP static void ThreadMapPort() { @@ -167,7 +273,7 @@ void StopMapPort() } } -#else +#else // #if defined(USE_NATPMP) || defined(USE_UPNP) void StartMapPort(bool use_upnp) { // Intentionally left blank. @@ -180,4 +286,4 @@ void StopMapPort() { // Intentionally left blank. } -#endif +#endif // #if defined(USE_NATPMP) || defined(USE_UPNP) diff --git a/src/mapport.h b/src/mapport.h index 329f35f67230..88fb2dff6b26 100644 --- a/src/mapport.h +++ b/src/mapport.h @@ -16,6 +16,7 @@ static const bool DEFAULT_UPNP = false; enum MapPortProtoFlag : unsigned int { NONE = 0x00, UPNP = 0x01, + NAT_PMP = 0x02, }; void StartMapPort(bool use_upnp); diff --git a/src/net.h b/src/net.h index e4ed7345d2d9..f0b6db6ec2c5 100644 --- a/src/net.h +++ b/src/net.h @@ -418,7 +418,7 @@ enum { LOCAL_NONE, // unknown LOCAL_IF, // address a local interface listens on LOCAL_BIND, // address explicit bound to - LOCAL_MAPPED, // address reported by UPnP + LOCAL_MAPPED, // address reported by UPnP or NAT-PMP LOCAL_MANUAL, // address explicitly specified (-externalip=) LOCAL_MAX diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index fd4131b419e9..8cc88cbc28e8 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -223,6 +223,10 @@ if(MINIUPNP_FOUND) target_link_libraries(pivx-qt ${MINIUPNP_LIBRARY}) target_include_directories(pivx-qt PUBLIC ${MINIUPNP_INCLUDE_DIR}) endif() +if(NAT-PMP_FOUND) + target_link_libraries(pivx-qt ${NAT-PMP_LIBRARY}) + target_include_directories(pivx-qt PUBLIC ${NAT-PMP_INCLUDE_DIR}) +endif() target_link_libraries(pivx-qt Qt5::Gui Qt5::Core Qt5::Widgets Qt5::Network Qt5::Svg ${QT_LIBRARIES}) if (Qt5DBus_FOUND) diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index db5df51ce43f..c18a36e32003 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -179,6 +179,10 @@ if(MINIUPNP_FOUND) target_link_libraries(test_pivx PRIVATE ${MINIUPNP_LIBRARY}) target_include_directories(test_pivx PRIVATE ${MINIUPNP_INCLUDE_DIR}) endif() +if(NAT-PMP_FOUND) + target_link_libraries(test_pivx PRIVATE ${NAT-PMP_LIBRARY}) + target_include_directories(test_pivx PRIVATE ${NAT-PMP_INCLUDE_DIR}) +endif() if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") target_link_libraries(test_pivx PRIVATE "-framework Cocoa") From 9927296d0ec0fa74e517a734e3a9d02c7ba756b8 Mon Sep 17 00:00:00 2001 From: Hennadii Stepanov <32963518+hebasto@users.noreply.github.com> Date: Sun, 23 Feb 2020 01:51:45 +0200 Subject: [PATCH 09/19] net: Add NAT-PMP to port mapping loop --- src/mapport.cpp | 60 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 7 deletions(-) diff --git a/src/mapport.cpp b/src/mapport.cpp index e023e2068bcd..40f7a0f979bb 100644 --- a/src/mapport.cpp +++ b/src/mapport.cpp @@ -41,7 +41,8 @@ static_assert(MINIUPNPC_API_VERSION >= 10, "miniUPnPc API version >= 10 assumed" #if defined(USE_NATPMP) || defined(USE_UPNP) static CThreadInterrupt g_mapport_interrupt; static std::thread g_mapport_thread; -static std::atomic_uint g_mapport_target_proto{MapPortProtoFlag::NONE}; +static std::atomic_uint g_mapport_enabled_protos{MapPortProtoFlag::NONE}; +static std::atomic g_mapport_current_proto{MapPortProtoFlag::NONE}; static constexpr auto PORT_MAPPING_REANNOUNCE_PERIOD = std::chrono::minutes(20); static constexpr auto PORT_MAPPING_RETRY_PERIOD = std::chrono::minutes(5); @@ -220,9 +221,34 @@ static bool ProcessUpnp() static void ThreadMapPort() { + bool ok; do { - if (ProcessUpnp()) return; - } while (g_mapport_interrupt.sleep_for(PORT_MAPPING_RETRY_PERIOD)); + ok = false; + +#ifdef USE_UPNP + // High priority protocol. + if (g_mapport_enabled_protos & MapPortProtoFlag::UPNP) { + g_mapport_current_proto = MapPortProtoFlag::UPNP; + ok = ProcessUpnp(); + if (ok) continue; + } +#endif // USE_UPNP + +#ifdef USE_NATPMP + // Low priority protocol. + if (g_mapport_enabled_protos & MapPortProtoFlag::NAT_PMP) { + g_mapport_current_proto = MapPortProtoFlag::NAT_PMP; + ok = ProcessNatpmp(); + if (ok) continue; + } +#endif // USE_NATPMP + + g_mapport_current_proto = MapPortProtoFlag::NONE; + if (g_mapport_enabled_protos == MapPortProtoFlag::NONE) { + return; + } + + } while (ok || g_mapport_interrupt.sleep_for(PORT_MAPPING_RETRY_PERIOD)); } void StartThreadMapPort() @@ -235,20 +261,39 @@ void StartThreadMapPort() static void DispatchMapPort() { - if (g_mapport_target_proto == MapPortProtoFlag::UPNP) { + if (g_mapport_current_proto == MapPortProtoFlag::NONE && g_mapport_enabled_protos == MapPortProtoFlag::NONE) { + return; + } + + if (g_mapport_current_proto == MapPortProtoFlag::NONE && g_mapport_enabled_protos != MapPortProtoFlag::NONE) { StartThreadMapPort(); - } else { + return; + } + + if (g_mapport_current_proto != MapPortProtoFlag::NONE && g_mapport_enabled_protos == MapPortProtoFlag::NONE) { InterruptMapPort(); StopMapPort(); + return; + } + + if (g_mapport_enabled_protos & g_mapport_current_proto) { + // Enabling another protocol does not cause switching from the currently used one. + return; } + + assert(g_mapport_thread.joinable()); + assert(!g_mapport_interrupt); + // Interrupt a protocol-specific loop in the ThreadUpnp() or in the ThreadNatpmp() + // to force trying the next protocol in the ThreadMapPort() loop. + g_mapport_interrupt(); } static void MapPortProtoSetEnabled(MapPortProtoFlag proto, bool enabled) { if (enabled) { - g_mapport_target_proto |= proto; + g_mapport_enabled_protos |= proto; } else { - g_mapport_target_proto &= ~proto; + g_mapport_enabled_protos &= ~proto; } } @@ -260,6 +305,7 @@ void StartMapPort(bool use_upnp) void InterruptMapPort() { + g_mapport_enabled_protos = MapPortProtoFlag::NONE; if (g_mapport_thread.joinable()) { g_mapport_interrupt(); } From 9a4ba4815fab48505ff5c3ca454e72f298db494e Mon Sep 17 00:00:00 2001 From: Fuzzbawls Date: Fri, 23 Apr 2021 03:15:45 -0700 Subject: [PATCH 10/19] net: Add -natpmp command line option --- src/init.cpp | 15 ++++++++++++--- src/mapport.cpp | 5 +++-- src/mapport.h | 15 ++++++++++----- src/qt/clientmodel.h | 2 +- src/qt/optionsmodel.cpp | 16 +++++++++++++++- src/qt/optionsmodel.h | 1 + .../settings/settingswalletoptionswidget.cpp | 2 +- test/functional/test_framework/util.py | 1 + 8 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 522869340f1b..cb28d190d310 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -503,6 +503,9 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-torcontrol=:", strprintf(_("Tor control port to use if onion listening enabled (default: %s)"), DEFAULT_TOR_CONTROL)); strUsage += HelpMessageOpt("-torpassword=", _("Tor control port password (default: empty)")); strUsage += HelpMessageOpt("-upnp", strprintf(_("Use UPnP to map the listening port (default: %u)"), DEFAULT_UPNP)); +#ifdef USE_NATPMP + strUsage += HelpMessageOpt("-natpmp", strprintf("Use NAT-PMP to map the listening port (default: %s)", DEFAULT_NATPMP ? "1 when listening and no -proxy" : "0")); +#endif // USE_NATPMP strUsage += HelpMessageOpt("-whitebind=", _("Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6")); strUsage += HelpMessageOpt("-whitelist=", _("Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times.") + " " + _("Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway")); @@ -915,10 +918,13 @@ void InitParameterInteraction() // to protect privacy, do not listen by default if a default proxy server is specified if (gArgs.SoftSetBoolArg("-listen", false)) LogPrintf("%s: parameter interaction: -proxy set -> setting -listen=0\n", __func__); - // to protect privacy, do not use UPNP when a proxy is set. The user may still specify -listen=1 + // to protect privacy, do not use map ports when a proxy is set. The user may still specify -listen=1 // to listen locally, so don't rely on this happening through -listen below. if (gArgs.SoftSetBoolArg("-upnp", false)) LogPrintf("%s: parameter interaction: -proxy set -> setting -upnp=0\n", __func__); + if (gArgs.SoftSetBoolArg("-natpmp", false)) { + LogPrintf("%s: parameter interaction: -proxy set -> setting -natpmp=0\n", __func__); + } // to protect privacy, do not discover addresses by default if (gArgs.SoftSetBoolArg("-discover", false)) LogPrintf("%s : parameter interaction: -proxy set -> setting -discover=0\n", __func__); @@ -928,6 +934,9 @@ void InitParameterInteraction() // do not map ports or try to retrieve public IP when not listening (pointless) if (gArgs.SoftSetBoolArg("-upnp", false)) LogPrintf("%s : parameter interaction: -listen=0 -> setting -upnp=0\n", __func__); + if (gArgs.SoftSetBoolArg("-natpmp", false)) { + LogPrintf("%s: parameter interaction: -listen=0 -> setting -natpmp=0\n", __func__); + } if (gArgs.SoftSetBoolArg("-discover", false)) LogPrintf("%s : parameter interaction: -listen=0 -> setting -discover=0\n", __func__); if (gArgs.SoftSetBoolArg("-listenonion", false)) @@ -1939,8 +1948,8 @@ bool AppInitMain() Discover(); - // Map ports with UPnP - StartMapPort(gArgs.GetBoolArg("-upnp", DEFAULT_UPNP)); + // Map ports with UPnP or NAT-PMP + StartMapPort(gArgs.GetBoolArg("-upnp", DEFAULT_UPNP), gArgs.GetBoolArg("-natpmp", DEFAULT_NATPMP)); std::string strNodeError; CConnman::Options connOptions; diff --git a/src/mapport.cpp b/src/mapport.cpp index 40f7a0f979bb..a83b73508316 100644 --- a/src/mapport.cpp +++ b/src/mapport.cpp @@ -297,9 +297,10 @@ static void MapPortProtoSetEnabled(MapPortProtoFlag proto, bool enabled) } } -void StartMapPort(bool use_upnp) +void StartMapPort(bool use_upnp, bool use_natpmp) { MapPortProtoSetEnabled(MapPortProtoFlag::UPNP, use_upnp); + MapPortProtoSetEnabled(MapPortProtoFlag::NAT_PMP, use_natpmp); DispatchMapPort(); } @@ -320,7 +321,7 @@ void StopMapPort() } #else // #if defined(USE_NATPMP) || defined(USE_UPNP) -void StartMapPort(bool use_upnp) +void StartMapPort(bool use_upnp, bool use_natpmp) { // Intentionally left blank. } diff --git a/src/mapport.h b/src/mapport.h index 88fb2dff6b26..34ca80b14575 100644 --- a/src/mapport.h +++ b/src/mapport.h @@ -6,12 +6,17 @@ #ifndef PIVX_MAPPORT_H #define PIVX_MAPPORT_H -/** -upnp default */ #ifdef USE_UPNP -static const bool DEFAULT_UPNP = USE_UPNP; +static constexpr bool DEFAULT_UPNP = USE_UPNP; #else -static const bool DEFAULT_UPNP = false; -#endif +static constexpr bool DEFAULT_UPNP = false; +#endif // USE_UPNP + +#ifdef USE_NATPMP +static constexpr bool DEFAULT_NATPMP = USE_NATPMP; +#else +static constexpr bool DEFAULT_NATPMP = false; +#endif // USE_NATPMP enum MapPortProtoFlag : unsigned int { NONE = 0x00, @@ -19,7 +24,7 @@ enum MapPortProtoFlag : unsigned int { NAT_PMP = 0x02, }; -void StartMapPort(bool use_upnp); +void StartMapPort(bool use_upnp, bool use_natpmp); void InterruptMapPort(); void StopMapPort(); diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 6e32d8891024..f06bb2d4ca9e 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -96,7 +96,7 @@ class ClientModel : public QObject bool getTorInfo(std::string& ip_port) const; - static void mapPort(bool use_upnp) { StartMapPort(use_upnp); } + static void mapPort(bool use_upnp, bool use_natpmp) { StartMapPort(use_upnp, use_natpmp); } // Start/Stop the masternode polling timer void startMasternodesTimer(); diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index b8674b92be58..3939828ecb0e 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -138,6 +138,11 @@ void OptionsModel::setNetworkDefaultOptions(QSettings& settings, bool reset) if (!gArgs.SoftSetBoolArg("-upnp", settings.value("fUseUPnP").toBool())) addOverriddenOption("-upnp"); + if (!settings.contains("fUseNatpmp") || reset ) + settings.setValue("fUseNatpmp", DEFAULT_NATPMP); + if (!gArgs.SoftSetBoolArg("-natpmp", settings.value("fUseNatpmp").toBool())) + addOverriddenOption("-natpmp"); + if (!settings.contains("fListen") || reset) settings.setValue("fListen", DEFAULT_LISTEN); if (!gArgs.SoftSetBoolArg("-listen", settings.value("fListen").toBool())) @@ -236,7 +241,13 @@ QVariant OptionsModel::data(const QModelIndex& index, int role) const return settings.value("fUseUPnP"); #else return false; -#endif +#endif // USE_UPNP + case MapPortNatpmp: +#ifdef USE_NATPMP + return settings.value("fUseNatpmp"); +#else + return false; +#endif // USE_NATPMP case MinimizeOnClose: return fMinimizeOnClose; @@ -310,6 +321,9 @@ bool OptionsModel::setData(const QModelIndex& index, const QVariant& value, int case MapPortUPnP: // core option - can be changed on-the-fly settings.setValue("fUseUPnP", value.toBool()); break; + case MapPortNatpmp: // core option - can be changed on-the-fly + settings.setValue("fUseNatpmp", value.toBool()); + break; case MinimizeOnClose: fMinimizeOnClose = value.toBool(); settings.setValue("fMinimizeOnClose", fMinimizeOnClose); diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index 8e7b81e5181c..6c72a28191a8 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -28,6 +28,7 @@ class OptionsModel : public QAbstractListModel StartAtStartup, // bool MinimizeToTray, // bool MapPortUPnP, // bool + MapPortNatpmp, // bool MinimizeOnClose, // bool ProxyUse, // bool ProxyIP, // QString diff --git a/src/qt/pivx/settings/settingswalletoptionswidget.cpp b/src/qt/pivx/settings/settingswalletoptionswidget.cpp index eebb9a5ba60f..84b6cfb3a911 100644 --- a/src/qt/pivx/settings/settingswalletoptionswidget.cpp +++ b/src/qt/pivx/settings/settingswalletoptionswidget.cpp @@ -57,7 +57,7 @@ SettingsWalletOptionsWidget::SettingsWalletOptionsWidget(PIVXGUI* _window, QWidg connect(ui->pushButtonClean, &QPushButton::clicked, [this] { Q_EMIT discardSettings(); }); connect(ui->pushButtonSave, &QPushButton::clicked, [this](){ - ClientModel::mapPort(ui->checkBoxMap->isChecked()); + ClientModel::mapPort(ui->checkBoxMap->isChecked(), false); }); } diff --git a/test/functional/test_framework/util.py b/test/functional/test_framework/util.py index de17d6fb3ad9..7faefbf7453c 100644 --- a/test/functional/test_framework/util.py +++ b/test/functional/test_framework/util.py @@ -316,6 +316,7 @@ def initialize_datadir(dirname, n): f.write("listenonion=0\n") f.write("spendzeroconfchange=1\n") f.write("printtoconsole=0\n") + f.write("natpmp=0\n") return datadir def get_datadir_path(dirname, n): From 5a5e3cf40ea5d07a6d3b3c81dd2cf862c2377da2 Mon Sep 17 00:00:00 2001 From: Fuzzbawls Date: Fri, 23 Apr 2021 03:33:54 -0700 Subject: [PATCH 11/19] gui: Add NAT-PMP network option --- .../settings/forms/settingswalletoptionswidget.ui | 12 +++++++++++- src/qt/pivx/settings/settingswalletoptionswidget.cpp | 12 +++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/qt/pivx/settings/forms/settingswalletoptionswidget.ui b/src/qt/pivx/settings/forms/settingswalletoptionswidget.ui index 8c0af9566890..8e9afc5f884b 100644 --- a/src/qt/pivx/settings/forms/settingswalletoptionswidget.ui +++ b/src/qt/pivx/settings/forms/settingswalletoptionswidget.ui @@ -290,12 +290,22 @@ 0 - + Map port using UPnP + + + + Automatically open the PIVX client port on the router. This only works when your router supports NAT-PMP and it is enabled. The external port could be random. + + + Map port using NAT-PMP + + + diff --git a/src/qt/pivx/settings/settingswalletoptionswidget.cpp b/src/qt/pivx/settings/settingswalletoptionswidget.cpp index 84b6cfb3a911..033b3567173d 100644 --- a/src/qt/pivx/settings/settingswalletoptionswidget.cpp +++ b/src/qt/pivx/settings/settingswalletoptionswidget.cpp @@ -32,7 +32,12 @@ SettingsWalletOptionsWidget::SettingsWalletOptionsWidget(PIVXGUI* _window, QWidg ui->spinBoxStakeSplitThreshold->setAttribute(Qt::WA_MacShowFocusRect, 0); setShadow(ui->spinBoxStakeSplitThreshold); - // Radio buttons +#ifndef USE_UPNP + ui->mapPortUpnp->setVisible(false); +#endif +#ifndef USE_NATPMP + ui->mapPortNatpmp->setVisible(false); +#endif // Title ui->labelTitleNetwork->setText(tr("Network")); @@ -57,7 +62,7 @@ SettingsWalletOptionsWidget::SettingsWalletOptionsWidget(PIVXGUI* _window, QWidg connect(ui->pushButtonClean, &QPushButton::clicked, [this] { Q_EMIT discardSettings(); }); connect(ui->pushButtonSave, &QPushButton::clicked, [this](){ - ClientModel::mapPort(ui->checkBoxMap->isChecked(), false); + ClientModel::mapPort(ui->mapPortUpnp->isChecked(), ui->mapPortNatpmp->isChecked()); }); } @@ -74,7 +79,8 @@ void SettingsWalletOptionsWidget::setMapper(QDataWidgetMapper *mapper) mapper->addMapping(ui->radioButtonSpend, OptionsModel::SpendZeroConfChange); // Network - mapper->addMapping(ui->checkBoxMap, OptionsModel::MapPortUPnP); + mapper->addMapping(ui->mapPortUpnp, OptionsModel::MapPortUPnP); + mapper->addMapping(ui->mapPortNatpmp, OptionsModel::MapPortNatpmp); mapper->addMapping(ui->checkBoxAllow, OptionsModel::Listen); mapper->addMapping(ui->checkBoxConnect, OptionsModel::ProxyUse); mapper->addMapping(ui->lineEditProxy, OptionsModel::ProxyIP); From cf992d0d81b3dbbb670e8e1e59195e68d4d1e43e Mon Sep 17 00:00:00 2001 From: Fuzzbawls Date: Fri, 23 Apr 2021 03:36:47 -0700 Subject: [PATCH 12/19] ci: Add libnatpmp-dev package to some builds --- .github/workflows/build-and-test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 548e70920380..a0956fe26f43 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -79,7 +79,7 @@ jobs: - name: macOS os: macos-10.15 - packages: python3 autoconf automake berkeley-db4 libtool boost miniupnpc pkg-config qt5 zmq libevent qrencode gmp libsodium rust + packages: python3 autoconf automake berkeley-db4 libtool boost miniupnpc libnatpmp pkg-config qt5 zmq libevent qrencode gmp libsodium rust cc: $(brew --prefix llvm)/bin/clang cxx: $(brew --prefix llvm)/bin/clang++ @@ -303,7 +303,7 @@ jobs: - name: x86_64 Linux [GOAL:install] [bionic] [no depends only system libs] os: ubuntu-18.04 host: x86_64-unknown-linux-gnu - apt_get: python3-zmq qtbase5-dev qttools5-dev-tools libqt5svg5-dev libqt5charts5-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libzmq3-dev libqrencode-dev libgmp-dev libsodium-dev cargo + apt_get: python3-zmq qtbase5-dev qttools5-dev-tools libqt5svg5-dev libqt5charts5-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev libdb5.3++-dev libminiupnpc-dev libnatpmp-dev libzmq3-dev libqrencode-dev libgmp-dev libsodium-dev cargo unit_tests: true no_depends: 1 goal: install From 7886374ff8cb38855a05f0b5357750dcbe3ff997 Mon Sep 17 00:00:00 2001 From: Fuzzbawls Date: Fri, 23 Apr 2021 03:47:21 -0700 Subject: [PATCH 13/19] doc: Add libnatpmp stuff --- depends/README.md | 2 ++ doc/build-osx.md | 2 +- doc/build-unix.md | 22 +++++++++++++++++----- doc/dependencies.md | 4 +++- doc/tor.md | 2 +- 5 files changed, 24 insertions(+), 8 deletions(-) diff --git a/depends/README.md b/depends/README.md index 5baf70979ada..6c9caa838016 100644 --- a/depends/README.md +++ b/depends/README.md @@ -80,6 +80,8 @@ The following can be set when running make: `make FOO=bar`
Don't download/build/cache libs needed to enable the wallet
NO_UPNP
Don't download/build/cache packages needed for enabling upnp
+
NO_NATPMP
+
Don't download/build/cache packages needed for enabling NAT-PMP
NO_RUST
Don't download/build/cache rust packages (including librustzcash)
ALLOW_HOST_PACKAGES
diff --git a/doc/build-osx.md b/doc/build-osx.md index 56777b83abde..a92961bfcbe8 100644 --- a/doc/build-osx.md +++ b/doc/build-osx.md @@ -16,7 +16,7 @@ Then install [Homebrew](https://brew.sh). Dependencies ---------------------- - brew install autoconf automake berkeley-db4 libtool boost miniupnpc pkg-config python3 qt5 zmq libevent qrencode gmp libsodium rust + brew install autoconf automake berkeley-db4 libtool boost miniupnpc libnatpmp pkg-config python3 qt5 zmq libevent qrencode gmp libsodium rust See [dependencies.md](dependencies.md) for a complete overview. diff --git a/doc/build-unix.md b/doc/build-unix.md index 6d07dd7c2edc..f7ae3bfacfcb 100644 --- a/doc/build-unix.md +++ b/doc/build-unix.md @@ -41,6 +41,7 @@ Optional dependencies: Library | Purpose | Description ------------|------------------|---------------------- miniupnpc | UPnP Support | Firewall-jumping support + libnatpmp | NAT-PMP Support | Firewall-jumping support libdb4.8 | Berkeley DB | Wallet storage (only needed when wallet enabled) qt | GUI | GUI toolkit (only needed when GUI enabled) univalue | Utility | JSON parsing and encoding (bundled version will be used unless --with-system-univalue passed to configure) @@ -93,9 +94,9 @@ Otherwise, you can build from self-compiled `depends` (see above). To build PIVX Core without wallet, see [*Disable-wallet mode*](/doc/build-unix.md#disable-wallet-mode) -Optional (see --with-miniupnpc and --enable-upnp-default): +Optional port mapping libraries (see: `--with-miniupnpc`, and `--enable-upnp-default`, `--with-natpmp`, `--enable-natpmp-default`): - sudo apt-get install libminiupnpc-dev + sudo apt install libminiupnpc-dev libnatpmp-dev ZMQ dependencies (provides ZMQ API): @@ -127,7 +128,7 @@ Build requirements: Optional: - sudo dnf install miniupnpc-devel zeromq-devel + sudo dnf install miniupnpc-devel libnatpmp-devel zeromq-devel To build with Qt 5 you need the following: @@ -144,12 +145,23 @@ miniupnpc [miniupnpc](http://miniupnp.free.fr/) may be used for UPnP port mapping. It can be downloaded from [here]( http://miniupnp.tuxfamily.org/files/). UPnP support is compiled in and -turned off by default. See the configure options for upnp behavior desired: +turned off by default. See the configure options for UPnp behavior desired: - --without-miniupnpc No UPnP support miniupnp not required + --without-miniupnpc No UPnP support, miniupnp not required --disable-upnp-default (the default) UPnP support turned off by default at runtime --enable-upnp-default UPnP support turned on by default at runtime +libnatpmp +--------- + +[libnatpmp](https://miniupnp.tuxfamily.org/libnatpmp.html) may be used for NAT-PMP port mapping. It can be downloaded +from [here](https://miniupnp.tuxfamily.org/files/). NAT-PMP support is compiled in and +turned off by default. See the configure options for NAT-PMP behavior desired: + + --without-natpmp No NAT-PMP support, libnatpmp not required + --disable-natpmp-default (the default) NAT-PMP support turned off by default at runtime + --enable-natpmp-default NAT-PMP support turned on by default at runtime + To build: tar -xzvf miniupnpc-1.6.tar.gz diff --git a/doc/dependencies.md b/doc/dependencies.md index 9ff685e6885a..0c997b60d274 100644 --- a/doc/dependencies.md +++ b/doc/dependencies.md @@ -15,6 +15,7 @@ These are the dependencies currently used by PIVX Core. You can find instruction | GCC | | [4.8+](https://gcc.gnu.org/) (C++11 support) | | | | | HarfBuzz-NG | | | | | | | libevent | [2.1.8-stable](https://github.com/libevent/libevent/releases) | 2.0.22 | No | | | +| libnatpmp | [20150609](https://miniupnp.tuxfamily.org/files) | | No | | | | libjpeg | | | | | [Yes](https://github.com/pivx-project/pivx/blob/master/depends/packages/qt.mk#L65) | | libpng | | | | | [Yes](https://github.com/pivx-project/pivx/blob/master/depends/packages/qt.mk#L64) | | librsvg | | | | | | @@ -36,7 +37,8 @@ Controlling dependencies Some dependencies are not needed in all configurations. The following are some factors that affect the dependency list. #### Options passed to `./configure` -* MiniUPnPc is not needed with `--with-miniupnpc=no`. +* MiniUPnPc is not needed with `--without-miniupnpc`. +* libnatpmp is not needed with `--without-natpmp`. * Berkeley DB is not needed with `--disable-wallet`. * Qt is not needed with `--without-gui`. * If the qrencode dependency is absent, QR support won't be added. To force an error when that happens, pass `--with-qrencode`. diff --git a/doc/tor.md b/doc/tor.md index fad40436dc94..773082f3d684 100644 --- a/doc/tor.md +++ b/doc/tor.md @@ -87,7 +87,7 @@ as well, use `discover` instead: ./pivxd ... -discover -and open port 51472 on your firewall (or use -upnp). +and open port 51472 on your firewall (or use port mapping, i.e., `-upnp` or `-natpmp`). If you only want to use Tor to reach .onion addresses, but not use it as a proxy for normal IPv4/IPv6 communication, use: From d48ef00ce563fea96fc07c13f787129e09950e32 Mon Sep 17 00:00:00 2001 From: Fuzzbawls Date: Fri, 23 Apr 2021 03:52:05 -0700 Subject: [PATCH 14/19] doc: Add release notes --- doc/release-notes.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/doc/release-notes.md b/doc/release-notes.md index 8f797359a950..41e4d625a9a7 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -83,6 +83,13 @@ Note that while multi-wallet is now fully supported, the RPC multi-wallet interf GUI changes ----------- +### Settings + +A new checkbox has been added to the wallet settings UI to enable or disable automatic port mapping with NAT-PMP. +If both UPnP and NAT-PMP are enabled, a successful allocation from UPnP prevails over one from NAT-PMP. + +Note: Successful automatic port mapping requires a router that supports either UPnP or NAT-PMP. + ### RPC-Console The GUI RPC-Console now accepts "parenthesized syntax", nested commands, and simple queries (see [PR #2282](https://github.com/PIVX-Project/PIVX/pull/2282). @@ -221,6 +228,12 @@ The minimum supported miniUPnPc API version is set to 10. This keeps compatibili OpenSSL is no longer used by PIVX Core +P2P and network changes +----------------------- + +- Added NAT-PMP port mapping support via [`libnatpmp`](https://miniupnp.tuxfamily.org/libnatpmp.html) + + Configuration changes --------------------- @@ -248,6 +261,11 @@ A new init option flag '-blocksdir' will allow one to keep the blockfiles extern A new configure flag has been introduced to allow more granular control over weather or not the PoW mining RPC commands are compiled into the wallet. By default they are not. This behavior can be overridden by passing `--enable-mining-rpc` to the `configure` script. +### Enable NAT-PMP port mapping at startup + +The `-natpmp` option has been added to use NAT-PMP to map the listening port. If both UPnP +and NAT-PMP are enabled, a successful allocation from UPnP prevails over one from NAT-PMP. + ### Removed startup options - `printstakemodifier` From f1951b521e81e87eb3223dfd89875d91b218f2d6 Mon Sep 17 00:00:00 2001 From: Fuzzbawls Date: Fri, 23 Apr 2021 19:50:30 -0700 Subject: [PATCH 15/19] Add libnatpmp to nightly snapcraft builds --- build-aux/snap/snapcraft.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build-aux/snap/snapcraft.yaml b/build-aux/snap/snapcraft.yaml index 187fbc1187a3..f05dc2d04fce 100644 --- a/build-aux/snap/snapcraft.yaml +++ b/build-aux/snap/snapcraft.yaml @@ -317,6 +317,7 @@ parts: - libsodium-dev - cargo - libminiupnpc-dev + - libnatpmp-dev - libzmq3-dev - libqt5gui5 - libqt5core5a @@ -352,6 +353,7 @@ parts: - libevent-2.1-6 - libevent-pthreads-2.1-6 - libminiupnpc10 + - libnatpmp1 - libnorm1 - libpgm-5.2-0 - libprotobuf10 From c4300c051e04de63c2c0499af08896a04529080d Mon Sep 17 00:00:00 2001 From: Fuzzbawls Date: Fri, 23 Apr 2021 21:08:38 -0700 Subject: [PATCH 16/19] Clang-Tidy up mapport.cpp --- src/mapport.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/mapport.cpp b/src/mapport.cpp index a83b73508316..888918093402 100644 --- a/src/mapport.cpp +++ b/src/mapport.cpp @@ -123,7 +123,7 @@ static bool ProcessNatpmp() { bool ret = false; natpmp_t natpmp; - struct in_addr external_ipv4_addr; + struct in_addr external_ipv4_addr{}; if (NatpmpInit(&natpmp) && NatpmpDiscover(&natpmp, external_ipv4_addr)) { bool external_ip_discovered = false; const uint16_t private_port = GetListenPort(); @@ -151,9 +151,9 @@ static bool ProcessUpnp() { bool ret = false; std::string port = strprintf("%u", GetListenPort()); - const char* multicastif = 0; - const char* minissdpdpath = 0; - struct UPNPDev* devlist = 0; + const char* multicastif = nullptr; + const char* minissdpdpath = nullptr; + struct UPNPDev* devlist = nullptr; char lanaddr[64]; int error = 0; @@ -163,8 +163,8 @@ static bool ProcessUpnp() devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, 2, &error); #endif - struct UPNPUrls urls; - struct IGDdatas data; + struct UPNPUrls urls{}; + struct IGDdatas data{}; int r; r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)); @@ -190,7 +190,7 @@ static bool ProcessUpnp() std::string strDesc = PACKAGE_NAME " " + FormatFullVersion(); do { - r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0"); + r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", nullptr, "0"); if (r != UPNPCOMMAND_SUCCESS) { ret = false; @@ -203,14 +203,14 @@ static bool ProcessUpnp() } while (g_mapport_interrupt.sleep_for(PORT_MAPPING_REANNOUNCE_PERIOD)); g_mapport_interrupt.reset(); - r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0); + r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", nullptr); LogPrintf("UPNP_DeletePortMapping() returned: %d\n", r); freeUPNPDevlist(devlist); devlist = nullptr; FreeUPNPUrls(&urls); } else { LogPrintf("No valid UPnP IGDs found\n"); freeUPNPDevlist(devlist); - devlist = 0; + devlist = nullptr; if (r != 0) FreeUPNPUrls(&urls); } From 81431390e4fc4067398a7e705170bcb6076ccb7f Mon Sep 17 00:00:00 2001 From: Fuzzbawls Date: Wed, 2 Jun 2021 02:56:29 -0700 Subject: [PATCH 17/19] GUI: Re-work port mapping saving --- src/qt/clientmodel.cpp | 5 +++++ src/qt/clientmodel.h | 4 ++-- src/qt/pivx/settings/settingswalletoptionswidget.cpp | 10 ++++++---- src/qt/pivx/settings/settingswalletoptionswidget.h | 2 ++ src/qt/pivx/settings/settingswidget.cpp | 3 +++ 5 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 51096dcabaa4..e12e44921d2e 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -15,6 +15,7 @@ #include "checkpoints.h" #include "clientversion.h" #include "interfaces/handler.h" +#include "mapport.h" #include "masternodeman.h" #include "net.h" #include "netbase.h" @@ -347,6 +348,10 @@ void ClientModel::unsubscribeFromCoreSignals() m_handler_notify_block_tip->disconnect(); } +void ClientModel::mapPort(bool use_upnp, bool use_natpmp) { + StartMapPort(use_upnp, use_natpmp); +} + bool ClientModel::getTorInfo(std::string& ip_port) const { proxyType onion; diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index f06bb2d4ca9e..93aa427b1ae1 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -9,7 +9,6 @@ #include "uint256.h" #include "chain.h" -#include "mapport.h" #include #include @@ -96,7 +95,8 @@ class ClientModel : public QObject bool getTorInfo(std::string& ip_port) const; - static void mapPort(bool use_upnp, bool use_natpmp) { StartMapPort(use_upnp, use_natpmp); } + //! Set the automatic port mapping options + static void mapPort(bool use_upnp, bool use_natpmp); // Start/Stop the masternode polling timer void startMasternodesTimer(); diff --git a/src/qt/pivx/settings/settingswalletoptionswidget.cpp b/src/qt/pivx/settings/settingswalletoptionswidget.cpp index 033b3567173d..f03214b5a822 100644 --- a/src/qt/pivx/settings/settingswalletoptionswidget.cpp +++ b/src/qt/pivx/settings/settingswalletoptionswidget.cpp @@ -60,10 +60,6 @@ SettingsWalletOptionsWidget::SettingsWalletOptionsWidget(PIVXGUI* _window, QWidg connect(ui->pushButtonSave, &QPushButton::clicked, [this] { Q_EMIT saveSettings(); }); connect(ui->pushButtonReset, &QPushButton::clicked, this, &SettingsWalletOptionsWidget::onResetClicked); connect(ui->pushButtonClean, &QPushButton::clicked, [this] { Q_EMIT discardSettings(); }); - - connect(ui->pushButtonSave, &QPushButton::clicked, [this](){ - ClientModel::mapPort(ui->mapPortUpnp->isChecked(), ui->mapPortNatpmp->isChecked()); - }); } void SettingsWalletOptionsWidget::onResetClicked() @@ -71,6 +67,7 @@ void SettingsWalletOptionsWidget::onResetClicked() QSettings settings; walletModel->resetWalletOptions(settings); clientModel->getOptionsModel()->setNetworkDefaultOptions(settings, true); + saveMapPortOptions(); inform(tr("Options reset succeed")); } @@ -130,6 +127,11 @@ void SettingsWalletOptionsWidget::discardWalletOnlyOptions() reloadWalletOptions(); } +void SettingsWalletOptionsWidget::saveMapPortOptions() +{ + clientModel->mapPort(ui->mapPortUpnp->isChecked(), ui->mapPortNatpmp->isChecked()); +} + SettingsWalletOptionsWidget::~SettingsWalletOptionsWidget(){ delete ui; } diff --git a/src/qt/pivx/settings/settingswalletoptionswidget.h b/src/qt/pivx/settings/settingswalletoptionswidget.h index 55a3f7f84905..665f4ecd57b1 100644 --- a/src/qt/pivx/settings/settingswalletoptionswidget.h +++ b/src/qt/pivx/settings/settingswalletoptionswidget.h @@ -25,6 +25,8 @@ class SettingsWalletOptionsWidget : public PWidget void discardWalletOnlyOptions(); bool saveWalletOnlyOptions(); + void saveMapPortOptions(); + Q_SIGNALS: void saveSettings(); void discardSettings(); diff --git a/src/qt/pivx/settings/settingswidget.cpp b/src/qt/pivx/settings/settingswidget.cpp index 99510cd387ef..5db04f16da5b 100644 --- a/src/qt/pivx/settings/settingswidget.cpp +++ b/src/qt/pivx/settings/settingswidget.cpp @@ -224,6 +224,9 @@ void SettingsWidget::onSaveOptionsClicked() return; } + // Save port mapping settings + settingsWalletOptionsWidget->saveMapPortOptions(); + if (mapper->submit()) { OptionsModel* optionsModel = this->clientModel->getOptionsModel(); if (optionsModel->isRestartRequired()) { From f2b62a397b6307749b6fae3edba5f332c7800c3e Mon Sep 17 00:00:00 2001 From: fanquake Date: Tue, 16 Feb 2021 23:06:30 -0800 Subject: [PATCH 18/19] build: use newer source for libnatpmp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The source we are currently using is from 2015. The upstream repo has received a small number of bug fixes and improvements since then. Including one that fixes an issue for Windows users: https://github.com/miniupnp/libnatpmp/pull/13. The source we are currently using is the most recent "official" release, however I don't think it's worth waiting for a new one. The maintainer was prompted to do so in Oct 2020, then again in Jan of this year, and no release has eventuated. Given libnatpmp is a new inclusion into our repository, I think we should be using this newer source. This also cleans up a few warnings we currently see in depends builds: ```bash Extracting libnatpmp... /home/ubuntu/bitcoin/depends/sources/libnatpmp-20150609.tar.gz: OK Preprocessing libnatpmp... Configuring libnatpmp... Building libnatpmp... make[1]: Entering directory '/home/ubuntu/bitcoin/depends/work/build/x86_64-w64-mingw32/libnatpmp/20150609-13efa1beb87' x86_64-w64-mingw32-gcc -Os -fPIC -Wall -DENABLE_STRNATPMPERR -c -o natpmp.o natpmp.c x86_64-w64-mingw32-gcc -Os -fPIC -Wall -DENABLE_STRNATPMPERR -c -o getgateway.o getgateway.c natpmp.c:42: warning: "EWOULDBLOCK" redefined 42 | #define EWOULDBLOCK WSAEWOULDBLOCK | In file included from natpmp.c:38: /usr/share/mingw-w64/include/errno.h:166: note: this is the location of the previous definition 166 | #define EWOULDBLOCK 140 | natpmp.c:43: warning: "ECONNREFUSED" redefined 43 | #define ECONNREFUSED WSAECONNREFUSED | In file included from natpmp.c:38: /usr/share/mingw-w64/include/errno.h:110: note: this is the location of the previous definition 110 | #define ECONNREFUSED 107 | natpmp.c:271:5: warning: ‘readnatpmpresponseorretry’ redeclared without dllimport attribute: previous dllimport ignored [-Wattributes] 271 | int readnatpmpresponseorretry(natpmp_t * p, natpmpresp_t * response) | ^~~~~~~~~~~~~~~~~~~~~~~~~ ar crs libnatpmp.a natpmp.o getgateway.o make[1]: Leaving directory '/home/ubuntu/bitcoin/depends/work/build/x86_64-w64-mingw32/libnatpmp/20150609-13efa1beb87' Staging libnatpmp... Postprocessing libnatpmp... Caching libnatpmp... ``` --- depends/packages/libnatpmp.mk | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/depends/packages/libnatpmp.mk b/depends/packages/libnatpmp.mk index a24f201859a0..db222da73096 100644 --- a/depends/packages/libnatpmp.mk +++ b/depends/packages/libnatpmp.mk @@ -1,11 +1,13 @@ package=libnatpmp -$(package)_version=20150609 -$(package)_download_path=https://miniupnp.tuxfamily.org/files/ -$(package)_file_name=$(package)-$($(package)_version).tar.gz -$(package)_sha256_hash=e1aa9c4c4219bc06943d6b2130f664daee213fb262fcb94dd355815b8f4536b0 +$(package)_version=4536032ae32268a45c073a4d5e91bbab4534773a +$(package)_download_path=https://github.com/miniupnp/libnatpmp/archive +$(package)_file_name=$($(package)_version).tar.gz +$(package)_sha256_hash=543b460aab26acf91e11d15e17d8798f845304199eea2d76c2f444ec749c5383 define $(package)_set_vars $(package)_build_opts=CC="$($(package)_cc)" + $(package)_build_opts_darwin=LIBTOOL="$($(package)_libtool)" + $(package)_build_env+=CFLAGS="$($(package)_cflags) $($(package)_cppflags)" AR="$($(package)_ar)" endef define $(package)_build_cmds From c19879783fa849b90c42a94e36e4d1ea012b90a9 Mon Sep 17 00:00:00 2001 From: Fuzzbawls Date: Wed, 16 Jun 2021 12:33:47 -0700 Subject: [PATCH 19/19] build: compile libnatpmp with -DNATPMP_STATICLIB on Windows This fixes linking issues and mirrors what we do with miniupnpc. --- configure.ac | 4 ++++ depends/packages/libnatpmp.mk | 1 + src/Makefile.am | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 2f96ea51cf55..2b0fefc6e65a 100644 --- a/configure.ac +++ b/configure.ac @@ -1398,6 +1398,9 @@ else fi AC_MSG_RESULT($use_natpmp_default) AC_DEFINE_UNQUOTED([USE_NATPMP], [$natpmp_setting], [NAT-PMP support not compiled if undefined, otherwise value (0 or 1) determines default state]) + if test x$TARGET_OS = xwindows; then + NATPMP_CPPFLAGS="-DSTATICLIB -DNATPMP_STATICLIB" + fi else AC_MSG_RESULT([no]) fi @@ -1537,6 +1540,7 @@ AC_SUBST(BOOST_LIBS) AC_SUBST(TESTDEFS) AC_SUBST(MINIUPNPC_CPPFLAGS) AC_SUBST(MINIUPNPC_LIBS) +AC_SUBST(NATPMP_CPPFLAGS) AC_SUBST(NATPMP_LIBS) AC_SUBST(EVENT_LIBS) AC_SUBST(EVENT_PTHREADS_LIBS) diff --git a/depends/packages/libnatpmp.mk b/depends/packages/libnatpmp.mk index db222da73096..cdcf8c0bf2c1 100644 --- a/depends/packages/libnatpmp.mk +++ b/depends/packages/libnatpmp.mk @@ -6,6 +6,7 @@ $(package)_sha256_hash=543b460aab26acf91e11d15e17d8798f845304199eea2d76c2f444ec7 define $(package)_set_vars $(package)_build_opts=CC="$($(package)_cc)" + $(package)_build_opts_mingw32=CPPFLAGS=-DNATPMP_STATICLIB $(package)_build_opts_darwin=LIBTOOL="$($(package)_libtool)" $(package)_build_env+=CFLAGS="$($(package)_cflags) $($(package)_cppflags)" AR="$($(package)_ar)" endef diff --git a/src/Makefile.am b/src/Makefile.am index f9d0ee976cbd..b4a257dbb03a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -318,7 +318,7 @@ obj/build.h: FORCE libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h # server: shared between pivxd and pivx-qt -libbitcoin_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS) +libbitcoin_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CPPFLAGS) $(NATPMP_CPPFLAGS) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS) libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libbitcoin_server_a_SOURCES = \ addrdb.cpp \