diff --git a/src/activemasternode.cpp b/src/activemasternode.cpp index 71711a04e8ffa..c31dc733a7fbb 100644 --- a/src/activemasternode.cpp +++ b/src/activemasternode.cpp @@ -7,7 +7,6 @@ #include "addrman.h" #include "bls/bls_wrapper.h" -#include "evo/providertx.h" #include "masternode-sync.h" #include "masternode.h" #include "masternodeconfig.h" @@ -147,7 +146,7 @@ void CActiveDeterministicMasternodeManager::Init() // Check socket connectivity const std::string& strService = info.service.ToString(); LogPrintf("%s: Checking inbound connection to '%s'\n", __func__, strService); - SOCKET hSocket; + SOCKET hSocket = INVALID_SOCKET; bool fConnected = ConnectSocketDirectly(info.service, hSocket, nConnectTimeout) && IsSelectableSocket(hSocket); CloseSocket(hSocket); diff --git a/src/init.cpp b/src/init.cpp index 938d3abfcb4c6..656607a06474f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -115,14 +115,6 @@ static EvoNotificationInterface* pEvoNotificationInterface = nullptr; static const char* DEFAULT_ASMAP_FILENAME="ip_asn.map"; -/** Used to pass flags to the Bind() function */ -enum BindFlags { - BF_NONE = 0, - BF_EXPLICIT = (1U << 0), - BF_REPORT_ERROR = (1U << 1), - BF_WHITELIST = (1U << 2), -}; - static const char* FEE_ESTIMATES_FILENAME = "fee_estimates.dat"; CClientUIInterface uiInterface; // Declared but not defined in guiinterface.h @@ -387,19 +379,6 @@ static void registerSignalHandler(int signal, void(*handler)(int)) } #endif -bool static Bind(CConnman& connman, const CService& addr, unsigned int flags) -{ - if (!(flags & BF_EXPLICIT) && !IsReachable(addr)) - return false; - std::string strError; - if (!connman.BindListenPort(addr, strError, (flags & BF_WHITELIST) != 0)) { - if (flags & BF_REPORT_ERROR) - return UIError(strError); - return false; - } - return true; -} - void OnRPCStarted() { uiInterface.NotifyBlockTip.connect(RPCNotifyBlockChange); @@ -1044,11 +1023,14 @@ bool AppInitParameterInteraction() // Make sure enough file descriptors are available // -bind and -whitebind can't be set when not listening - size_t nUserBind = gArgs.GetArgs("-bind").size() + gArgs.GetArgs("-whitebind").size(); + size_t nUserBind = + (gArgs.IsArgSet("-bind") ? gArgs.GetArgs("-bind").size() : 0) + + (gArgs.IsArgSet("-whitebind") ? gArgs.GetArgs("-whitebind").size() : 0); if (nUserBind != 0 && !gArgs.GetBoolArg("-listen", DEFAULT_LISTEN)) { return UIError(strprintf(_("Cannot set %s or %s together with %s"), "-bind", "-whitebind", "-listen=0")); } + // Make sure enough file descriptors are available int nBind = std::max(nUserBind, size_t(1)); nUserMaxConnections = gArgs.GetArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS); nMaxConnections = std::max(nUserMaxConnections, 0); @@ -1391,14 +1373,6 @@ bool AppInitMain() } } - for (const auto& net : gArgs.GetArgs("-whitelist")) { - CSubNet subnet; - LookupSubNet(net, subnet); - if (!subnet.IsValid()) - return UIError(strprintf(_("Invalid netmask specified in %s: '%s'"), "-whitelist", net)); - connman.AddWhitelistedRange(subnet); - } - // Check for host lookup allowed before parsing any network related parameters fNameLookup = gArgs.GetBoolArg("-dns", DEFAULT_NAME_LOOKUP); @@ -1448,32 +1422,6 @@ bool AppInitMain() fListen = gArgs.GetBoolArg("-listen", DEFAULT_LISTEN); fDiscover = gArgs.GetBoolArg("-discover", true); - bool fBound = false; - if (fListen) { - for (const std::string& strBind : gArgs.GetArgs("-bind")) { - CService addrBind; - if (!Lookup(strBind, addrBind, GetListenPort(), false)) - return UIError(ResolveErrMsg("bind", strBind)); - fBound |= Bind(connman, addrBind, (BF_EXPLICIT | BF_REPORT_ERROR)); - } - for (const std::string& strBind : gArgs.GetArgs("-whitebind")) { - CService addrBind; - if (!Lookup(strBind, addrBind, 0, false)) - return UIError(ResolveErrMsg("whitebind", strBind)); - if (addrBind.GetPort() == 0) - return UIError(strprintf(_("Need to specify a port with %s: '%s'"), "-whitebind", strBind)); - fBound |= Bind(connman, addrBind, (BF_EXPLICIT | BF_REPORT_ERROR | BF_WHITELIST)); - } - if (!gArgs.IsArgSet("-bind") && !gArgs.IsArgSet("-whitebind")) { - struct in_addr inaddr_any; - inaddr_any.s_addr = INADDR_ANY; - fBound |= Bind(connman, CService((in6_addr)IN6ADDR_ANY_INIT, GetListenPort()), BF_NONE); - fBound |= Bind(connman, CService(inaddr_any, GetListenPort()), !fBound ? BF_REPORT_ERROR : BF_NONE); - } - if (!fBound) - return UIError(strprintf(_("Failed to listen on any port. Use %s if you want this."), "-listen=0")); - } - for (const std::string& strAddr : gArgs.GetArgs("-externalip")) { CService addrLocal; if (Lookup(strAddr, addrLocal, GetListenPort(), fNameLookup) && addrLocal.IsValid()) @@ -1512,11 +1460,6 @@ bool AppInitMain() // on the command line or in this network's section of the config file. gArgs.WarnForSectionOnlyArgs(); - if (gArgs.IsArgSet("-seednode")) { - for (const std::string& strDest : gArgs.GetArgs("-seednode")) - connman.AddOneShot(strDest); - } - #if ENABLE_ZMQ pzmqNotificationInterface = CZMQNotificationInterface::Create(); @@ -1971,7 +1914,6 @@ bool AppInitMain() // Map ports with UPnP or NAT-PMP StartMapPort(gArgs.GetBoolArg("-upnp", DEFAULT_UPNP), gArgs.GetBoolArg("-natpmp", DEFAULT_NATPMP)); - std::string strNodeError; CConnman::Options connOptions; connOptions.nLocalServices = nLocalServices; connOptions.nRelevantServices = nRelevantServices; @@ -1984,9 +1926,51 @@ bool AppInitMain() connOptions.m_msgproc = peerLogic.get(); connOptions.nSendBufferMaxSize = 1000*gArgs.GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER); connOptions.nReceiveFloodSize = 1000*gArgs.GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER); + connOptions.m_added_nodes = gArgs.GetArgs("-addnode"); - if (!connman.Start(scheduler, strNodeError, connOptions)) - return UIError(strNodeError); + if (gArgs.IsArgSet("-bind")) { + for (const std::string& strBind : gArgs.GetArgs("-bind")) { + CService addrBind; + if (!Lookup(strBind, addrBind, GetListenPort(), false)) { + return UIError(ResolveErrMsg("bind", strBind)); + } + connOptions.vBinds.emplace_back(addrBind); + } + } + if (gArgs.IsArgSet("-whitebind")) { + for (const std::string& strBind : gArgs.GetArgs("-whitebind")) { + CService addrBind; + if (!Lookup(strBind, addrBind, 0, false)) { + return UIError(ResolveErrMsg("whitebind", strBind)); + } + if (addrBind.GetPort() == 0) { + return UIError(strprintf(_("Need to specify a port with %s: '%s'"), "-whitebind", strBind)); + } + connOptions.vWhiteBinds.emplace_back(addrBind); + } + } + + for (const auto& net : gArgs.GetArgs("-whitelist")) { + CSubNet subnet; + LookupSubNet(net, subnet); + if (!subnet.IsValid()) + return UIError(strprintf(_("Invalid netmask specified in %s: '%s'"), "-whitelist", net)); + connOptions.vWhitelistedRange.emplace_back(subnet); + } + + connOptions.vSeedNodes = gArgs.GetArgs("-seednode"); + + // Initiate outbound connections unless connect=0 + connOptions.m_use_addrman_outgoing = !gArgs.IsArgSet("-connect"); + if (!connOptions.m_use_addrman_outgoing) { + const auto connect = gArgs.GetArgs("-connect"); + if (connect.size() != 1 || connect[0] != "0") { + connOptions.m_specified_outgoing = connect; + } + } + if (!connman.Start(scheduler, connOptions)) { + return false; + } #ifdef ENABLE_WALLET // Generate coins in the background (disabled on mainnet. use only wallet 0) diff --git a/src/net.cpp b/src/net.cpp index df4629b972704..2272d602235b1 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -59,6 +59,14 @@ #endif #endif +/** Used to pass flags to the Bind() function */ +enum BindFlags { + BF_NONE = 0, + BF_EXPLICIT = (1U << 0), + BF_REPORT_ERROR = (1U << 1), + BF_WHITELIST = (1U << 2), +}; + const static std::string NET_MESSAGE_COMMAND_OTHER = "*other*"; static const uint64_t RANDOMIZER_ID_NETGROUP = 0x6c0edd8036ef4036ULL; // SHA256("netgroup")[0:8] @@ -607,7 +615,6 @@ void CConnman::SetBannedSetDirty(bool dirty) bool CConnman::IsWhitelistedRange(const CNetAddr& addr) { - LOCK(cs_vWhitelistedRange); for (const CSubNet& subnet : vWhitelistedRange) { if (subnet.Match(addr)) return true; @@ -615,13 +622,6 @@ bool CConnman::IsWhitelistedRange(const CNetAddr& addr) return false; } -void CConnman::AddWhitelistedRange(const CSubNet& subnet) -{ - LOCK(cs_vWhitelistedRange); - vWhitelistedRange.push_back(subnet); -} - - std::string CNode::GetAddrName() const { LOCK(cs_addrName); return addrName; @@ -1483,13 +1483,13 @@ void CConnman::ProcessOneShot() } } -void CConnman::ThreadOpenConnections() +void CConnman::ThreadOpenConnections(const std::vector connect) { // Connect to specific addresses - if (gArgs.IsArgSet("-connect")) { + if (!connect.empty()) { for (int64_t nLoop = 0;; nLoop++) { ProcessOneShot(); - for (const std::string& strAddr : gArgs.GetArgs("-connect")) { + for (const std::string& strAddr : connect) { CAddress addr(CService(), NODE_NONE); OpenNetworkConnection(addr, false, nullptr, strAddr.c_str()); for (int i = 0; i < 10 && i < nLoop; i++) { @@ -1694,11 +1694,6 @@ std::vector CConnman::GetAddedNodeInfo() void CConnman::ThreadOpenAddedConnections() { - { - LOCK(cs_vAddedNodes); - vAddedNodes = gArgs.GetArgs("-addnode"); - } - while (true) { CSemaphoreGrant grant(*semAddnode); std::vector vInfo = GetAddedNodeInfo(); @@ -1926,12 +1921,10 @@ CConnman::CConnman(uint64_t nSeed0In, uint64_t nSeed1In) : nSeed0(nSeed0In), nSe nLastNodeId = 0; nSendBufferMaxSize = 0; nReceiveFloodSize = 0; - nMaxConnections = 0; - nMaxOutbound = 0; - nMaxAddnode = 0; - nBestHeight = 0; - clientInterface = nullptr; flagInterruptMsgProc = false; + + Options connOptions; + Init(connOptions); } NodeId CConnman::GetNewNodeId() @@ -1939,24 +1932,62 @@ NodeId CConnman::GetNewNodeId() return nLastNodeId.fetch_add(1, std::memory_order_relaxed); } -bool CConnman::Start(CScheduler& scheduler, std::string& strNodeError, Options connOptions) +bool CConnman::Bind(const CService& addr, unsigned int flags) { + if (!(flags & BF_EXPLICIT) && !IsReachable(addr)) + return false; + std::string strError; + if (!BindListenPort(addr, strError, (flags & BF_WHITELIST) != 0)) { + if ((flags & BF_REPORT_ERROR) && clientInterface) { + clientInterface->ThreadSafeMessageBox(strError, "", CClientUIInterface::MSG_ERROR); + } + return false; + } + return true; +} + +bool CConnman::InitBinds(const std::vector& binds, const std::vector& whiteBinds) { + bool fBound = false; + for (const auto& addrBind : binds) { + fBound |= Bind(addrBind, (BF_EXPLICIT | BF_REPORT_ERROR)); + } + for (const auto& addrBind : whiteBinds) { + fBound |= Bind(addrBind, (BF_EXPLICIT | BF_REPORT_ERROR | BF_WHITELIST)); + } + if (binds.empty() && whiteBinds.empty()) { + struct in_addr inaddr_any; + inaddr_any.s_addr = INADDR_ANY; + fBound |= Bind(CService((in6_addr)IN6ADDR_ANY_INIT, GetListenPort()), BF_NONE); + fBound |= Bind(CService(inaddr_any, GetListenPort()), !fBound ? BF_REPORT_ERROR : BF_NONE); + } + return fBound; +} + +bool CConnman::Start(CScheduler& scheduler, const Options& connOptions) { - nTotalBytesRecv = 0; - nTotalBytesSent = 0; + Init(connOptions); - nRelevantServices = connOptions.nRelevantServices; - nLocalServices = connOptions.nLocalServices; - nMaxConnections = connOptions.nMaxConnections; - nMaxOutbound = std::min(connOptions.nMaxOutbound, nMaxConnections); - nMaxAddnode = connOptions.nMaxAddnode; - nMaxFeeler = connOptions.nMaxFeeler; + { + LOCK(cs_totalBytesRecv); + nTotalBytesRecv = 0; + } + { + LOCK(cs_totalBytesSent); + nTotalBytesSent = 0; + } - nSendBufferMaxSize = connOptions.nSendBufferMaxSize; - nReceiveFloodSize = connOptions.nReceiveFloodSize; + if (fListen && !InitBinds(connOptions.vBinds, connOptions.vWhiteBinds)) { + if (clientInterface) { + clientInterface->ThreadSafeMessageBox( + _("Failed to listen on any port. Use -listen=0 if you want this."), + "", CClientUIInterface::MSG_ERROR); + } + return false; + } - SetBestHeight(connOptions.nBestHeight); + for (const auto& strDest : connOptions.vSeedNodes) { + AddOneShot(strDest); + } - clientInterface = connOptions.uiInterface; if (clientInterface) clientInterface->InitMessage(_("Loading addresses...")); m_msgproc = connOptions.m_msgproc; @@ -2030,9 +2061,18 @@ bool CConnman::Start(CScheduler& scheduler, std::string& strNodeError, Options c // Initiate outbound connections from -addnode threadOpenAddedConnections = std::thread(&TraceThread >, "addcon", std::function(std::bind(&CConnman::ThreadOpenAddedConnections, this))); - // Initiate outbound connections unless connect=0 - if (!gArgs.IsArgSet("-connect") || gArgs.GetArgs("-connect").size() != 1 || gArgs.GetArgs("-connect")[0] != "0") - threadOpenConnections = std::thread(&TraceThread >, "opencon", std::function(std::bind(&CConnman::ThreadOpenConnections, this))); + if (connOptions.m_use_addrman_outgoing && !connOptions.m_specified_outgoing.empty()) { + if (clientInterface) { + clientInterface->ThreadSafeMessageBox( + _("Cannot provide specific connections and have addrman find outgoing connections at the same."), + "", CClientUIInterface::MSG_ERROR); + } + return false; + } + if (connOptions.m_use_addrman_outgoing || !connOptions.m_specified_outgoing.empty()) { + threadOpenConnections = std::thread(&TraceThread >, "opencon", std::function( + std::bind(&CConnman::ThreadOpenConnections, this, connOptions.m_specified_outgoing))); + } // Process messages threadMessageHandler = std::thread(&TraceThread >, "msghand", std::function(std::bind(&CConnman::ThreadMessageHandler, this))); diff --git a/src/net.h b/src/net.h index 777506fe73e20..3dda9f9b34d4b 100644 --- a/src/net.h +++ b/src/net.h @@ -142,13 +142,37 @@ class CConnman unsigned int nSendBufferMaxSize = 0; unsigned int nReceiveFloodSize = 0; std::vector m_asmap; + std::vector vSeedNodes; + std::vector vWhitelistedRange; + std::vector vBinds, vWhiteBinds; + bool m_use_addrman_outgoing = true; + std::vector m_specified_outgoing; + std::vector m_added_nodes; }; + + void Init(const Options& connOptions) { + nLocalServices = connOptions.nLocalServices; + nRelevantServices = connOptions.nRelevantServices; + nMaxConnections = connOptions.nMaxConnections; + nMaxOutbound = std::min(connOptions.nMaxOutbound, connOptions.nMaxConnections); + nMaxAddnode = connOptions.nMaxAddnode; + nMaxFeeler = connOptions.nMaxFeeler; + nBestHeight = connOptions.nBestHeight; + clientInterface = connOptions.uiInterface; + nSendBufferMaxSize = connOptions.nSendBufferMaxSize; + nReceiveFloodSize = connOptions.nReceiveFloodSize; + vWhitelistedRange = connOptions.vWhitelistedRange; + { + LOCK(cs_vAddedNodes); + vAddedNodes = connOptions.m_added_nodes; + } + } + CConnman(uint64_t seed0, uint64_t seed1); ~CConnman(); - bool Start(CScheduler& scheduler, std::string& strNodeError, Options options); + bool Start(CScheduler& scheduler, const Options& options); void Stop(); void Interrupt(); - bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); void OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant* grantOutbound = nullptr, const char* strDest = nullptr, bool fOneShot = false, bool fFeeler = false, bool fAddnode = false); bool CheckIncomingNonce(uint64_t nonce); @@ -271,8 +295,6 @@ class CConnman void GetBanned(banmap_t &banmap); void SetBanned(const banmap_t &banmap); - void AddOneShot(const std::string& strDest); - bool AddNode(const std::string& node); bool RemoveAddedNode(const std::string& node); std::vector GetAddedNodeInfo(); @@ -284,8 +306,6 @@ class CConnman unsigned int GetSendBufferSize() const; - void AddWhitelistedRange(const CSubNet& subnet); - ServiceFlags GetLocalServices() const; uint64_t GetTotalBytesRecv(); @@ -308,9 +328,13 @@ class CConnman ListenSocket(SOCKET socket_, bool whitelisted_) : socket(socket_), whitelisted(whitelisted_) {} }; + bool BindListenPort(const CService& bindAddr, std::string& strError, bool fWhitelisted = false); + bool Bind(const CService& addr, unsigned int flags); + bool InitBinds(const std::vector& binds, const std::vector& whiteBinds); void ThreadOpenAddedConnections(); + void AddOneShot(const std::string& strDest); void ProcessOneShot(); - void ThreadOpenConnections(); + void ThreadOpenConnections(const std::vector connect); void ThreadMessageHandler(); void AcceptConnection(const ListenSocket& hListenSocket); void ThreadSocketHandler(); @@ -354,13 +378,12 @@ class CConnman // Network usage totals RecursiveMutex cs_totalBytesRecv; RecursiveMutex cs_totalBytesSent; - uint64_t nTotalBytesRecv{0}; - uint64_t nTotalBytesSent{0}; + uint64_t nTotalBytesRecv GUARDED_BY(cs_totalBytesRecv) = 0; + uint64_t nTotalBytesSent GUARDED_BY(cs_totalBytesSent) = 0; // Whitelisted ranges. Any node connecting from these is automatically // whitelisted (as well as those connecting to whitelisted binds). std::vector vWhitelistedRange; - RecursiveMutex cs_vWhitelistedRange; unsigned int nSendBufferMaxSize{0}; unsigned int nReceiveFloodSize{0}; @@ -373,7 +396,7 @@ class CConnman CAddrMan addrman; std::deque vOneShots; RecursiveMutex cs_vOneShots; - std::vector vAddedNodes; + std::vector vAddedNodes GUARDED_BY(cs_vAddedNodes); RecursiveMutex cs_vAddedNodes; std::vector vNodes; std::list vNodesDisconnected; diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 48e518696567c..887126e98f916 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1115,6 +1115,7 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR std::string strSubVer; std::string cleanSubVer; int nStartingHeight = -1; + bool fRelay = true; vRecv >> nVersion >> nServiceInt >> nTime >> addrMe; nSendVersion = std::min(nVersion, PROTOCOL_VERSION); nServices = ServiceFlags(nServiceInt); @@ -1142,6 +1143,9 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR if (!vRecv.empty()) { vRecv >> nStartingHeight; } + if (!vRecv.empty()) { + vRecv >> fRelay; + } // Disconnect if we connected to ourself if (pfrom->fInbound && !connman->CheckIncomingNonce(nNonce)) { @@ -1183,11 +1187,7 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR { LOCK(pfrom->cs_filter); - if (!vRecv.empty()) { - vRecv >> pfrom->fRelayTxes; // set to true after we get the first filter* message - } else { - pfrom->fRelayTxes = true; - } + pfrom->fRelayTxes = fRelay; // set to true after we get the first filter* message } // Change version