Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[net] Connman options encapsulation #2632

Merged
merged 11 commits into from
Dec 7, 2021
3 changes: 1 addition & 2 deletions src/activemasternode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);

Expand Down
112 changes: 48 additions & 64 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -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;
Expand All @@ -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)
Expand Down
114 changes: 77 additions & 37 deletions src/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -607,21 +615,13 @@ 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;
}
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;
Expand Down Expand Up @@ -1483,13 +1483,13 @@ void CConnman::ProcessOneShot()
}
}

void CConnman::ThreadOpenConnections()
void CConnman::ThreadOpenConnections(const std::vector<std::string> 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++) {
Expand Down Expand Up @@ -1694,11 +1694,6 @@ std::vector<AddedNodeInfo> CConnman::GetAddedNodeInfo()

void CConnman::ThreadOpenAddedConnections()
{
{
LOCK(cs_vAddedNodes);
vAddedNodes = gArgs.GetArgs("-addnode");
}

while (true) {
CSemaphoreGrant grant(*semAddnode);
std::vector<AddedNodeInfo> vInfo = GetAddedNodeInfo();
Expand Down Expand Up @@ -1926,37 +1921,73 @@ 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()
{
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<CService>& binds, const std::vector<CService>& 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;
Expand Down Expand Up @@ -2030,9 +2061,18 @@ bool CConnman::Start(CScheduler& scheduler, std::string& strNodeError, Options c
// Initiate outbound connections from -addnode
threadOpenAddedConnections = std::thread(&TraceThread<std::function<void()> >, "addcon", std::function<void()>(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<std::function<void()> >, "opencon", std::function<void()>(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<std::function<void()> >, "opencon", std::function<void()>(
std::bind(&CConnman::ThreadOpenConnections, this, connOptions.m_specified_outgoing)));
}

// Process messages
threadMessageHandler = std::thread(&TraceThread<std::function<void()> >, "msghand", std::function<void()>(std::bind(&CConnman::ThreadMessageHandler, this)));
Expand Down
Loading