Skip to content

Commit

Permalink
add Binds, WhiteBinds to CConnman::Options
Browse files Browse the repository at this point in the history
Part of a series of changes to clean up the instantiation of connman by decoupling the command line arguments.  We also now abort with an error when explicit binds are set with -listen=0.

Coming from btc@ce79f3251851f6177f38009341802e6065cb70af
  • Loading branch information
Marko Bencun authored and furszy committed Nov 22, 2021
1 parent 41c89af commit d9e91ff
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 55 deletions.
80 changes: 29 additions & 51 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 @@ -1440,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 @@ -1963,7 +1919,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 @@ -1977,6 +1932,28 @@ bool AppInitMain()
connOptions.nSendBufferMaxSize = 1000*gArgs.GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER);
connOptions.nReceiveFloodSize = 1000*gArgs.GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER);

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);
Expand All @@ -1985,8 +1962,9 @@ bool AppInitMain()
connOptions.vWhitelistedRange.emplace_back(subnet);
}

if (!connman.Start(scheduler, strNodeError, connOptions))
return UIError(strNodeError);
if (!connman.Start(scheduler, connOptions)) {
return false;
}

#ifdef ENABLE_WALLET
// Generate coins in the background (disabled on mainnet. use only wallet 0)
Expand Down
52 changes: 50 additions & 2 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 @@ -1931,7 +1939,37 @@ 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, Options connOptions)
{
nTotalBytesRecv = 0;
nTotalBytesSent = 0;
Expand All @@ -1948,9 +1986,19 @@ bool CConnman::Start(CScheduler& scheduler, std::string& strNodeError, Options c

SetBestHeight(connOptions.nBestHeight);

clientInterface = connOptions.uiInterface;

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;
}

vWhitelistedRange = connOptions.vWhitelistedRange;

clientInterface = connOptions.uiInterface;
if (clientInterface)
clientInterface->InitMessage(_("Loading addresses..."));
m_msgproc = connOptions.m_msgproc;
Expand Down
7 changes: 5 additions & 2 deletions src/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,13 @@ class CConnman
unsigned int nReceiveFloodSize = 0;
std::vector<bool> m_asmap;
std::vector<CSubNet> vWhitelistedRange;
std::vector<CService> vBinds, vWhiteBinds;
};
CConnman(uint64_t seed0, uint64_t seed1);
~CConnman();
bool Start(CScheduler& scheduler, std::string& strNodeError, Options options);
bool Start(CScheduler& scheduler, 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);

Expand Down Expand Up @@ -307,6 +307,9 @@ 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<CService>& binds, const std::vector<CService>& whiteBinds);
void ThreadOpenAddedConnections();
void ProcessOneShot();
void ThreadOpenConnections();
Expand Down

0 comments on commit d9e91ff

Please sign in to comment.