Skip to content

Commit e3cae52

Browse files
committed
Added -whiteconnections=<n> option
This sets aside a number of connection slots for whitelisted peers, useful for ensuring your local users and miners can always get in, even if your limit on inbound connections has already been reached.
1 parent ab0ec67 commit e3cae52

File tree

3 files changed

+68
-11
lines changed

3 files changed

+68
-11
lines changed

src/init.cpp

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ std::string HelpMessage(HelpMessageMode mode)
328328
strUsage += HelpMessageOpt("-whitebind=<addr>", _("Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6"));
329329
strUsage += HelpMessageOpt("-whitelist=<netmask>", _("Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times.") +
330330
" " + _("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"));
331+
strUsage += HelpMessageOpt("-whiteconnections=<n>", strprintf(_("Reserve this many inbound connections for whitelisted peers (default: %d)"), 0));
331332

332333
#ifdef ENABLE_WALLET
333334
strUsage += HelpMessageGroup(_("Wallet options:"));
@@ -723,16 +724,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
723724
LogPrintf("%s: parameter interaction: -zapwallettxes=<mode> -> setting -rescan=1\n", __func__);
724725
}
725726

726-
// Make sure enough file descriptors are available
727-
int nBind = std::max((int)mapArgs.count("-bind") + (int)mapArgs.count("-whitebind"), 1);
728-
nMaxConnections = GetArg("-maxconnections", 125);
729-
nMaxConnections = std::max(std::min(nMaxConnections, (int)(FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS)), 0);
730-
int nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS);
731-
if (nFD < MIN_CORE_FILEDESCRIPTORS)
732-
return InitError(_("Not enough file descriptors available."));
733-
if (nFD - MIN_CORE_FILEDESCRIPTORS < nMaxConnections)
734-
nMaxConnections = nFD - MIN_CORE_FILEDESCRIPTORS;
735-
736727
// if using block pruning, then disable txindex
737728
if (GetArg("-prune", 0)) {
738729
if (GetBoolArg("-txindex", false))
@@ -743,6 +734,47 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
743734
}
744735
#endif
745736
}
737+
738+
// Make sure enough file descriptors are available
739+
int nBind = std::max((int)mapArgs.count("-bind") + (int)mapArgs.count("-whitebind"), 1);
740+
int nUserMaxConnections = GetArg("-maxconnections", 125);
741+
nMaxConnections = std::max(nUserMaxConnections, 0);
742+
int nUserWhiteConnections = GetArg("-whiteconnections", 0);
743+
nWhiteConnections = std::max(nUserWhiteConnections, 0);
744+
745+
if ((mapArgs.count("-whitelist")) || (mapArgs.count("-whitebind"))) {
746+
if (!(mapArgs.count("-maxconnections"))) {
747+
// User is using whitelist feature,
748+
// but did not specify -maxconnections parameter.
749+
// Silently increase the default to compensate,
750+
// so that the whitelist connection reservation feature
751+
// does not inadvertently reduce the default
752+
// inbound connection capacity of the network.
753+
nMaxConnections += nWhiteConnections;
754+
}
755+
} else {
756+
// User not using whitelist feature.
757+
// Silently disable connection reservation,
758+
// for the same reason as above.
759+
nWhiteConnections = 0;
760+
}
761+
762+
// Trim requested connection counts, to fit into system limitations
763+
nMaxConnections = std::max(std::min(nMaxConnections, (int)(FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS)), 0);
764+
int nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS);
765+
if (nFD < MIN_CORE_FILEDESCRIPTORS)
766+
return InitError(_("Not enough file descriptors available."));
767+
nMaxConnections = std::min(nFD - MIN_CORE_FILEDESCRIPTORS, nMaxConnections);
768+
769+
if (nMaxConnections < nUserMaxConnections)
770+
InitWarning(strprintf(_("Reducing -maxconnections from %d to %d, because of system limitations."), nUserMaxConnections, nMaxConnections));
771+
772+
// Connection capacity is prioritized in this order:
773+
// outbound connections (hardcoded to 8),
774+
// then whitelisted connections,
775+
// then non-whitelisted connections get whatever's left (if any).
776+
if ((nWhiteConnections > 0) && (nWhiteConnections >= (nMaxConnections - 8)))
777+
InitWarning(strprintf(_("All non-whitelisted incoming connections will be dropped, because -whiteconnections is %d and -maxconnections is only %d."), nWhiteConnections, nMaxConnections));
746778

747779
// ********************************************************* Step 3: parameter-to-internal-flags
748780

@@ -910,6 +942,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
910942
LogPrintf("Using data directory %s\n", strDataDir);
911943
LogPrintf("Using config file %s\n", GetConfigFile().string());
912944
LogPrintf("Using at most %i connections (%i file descriptors available)\n", nMaxConnections, nFD);
945+
if (nWhiteConnections > 0)
946+
LogPrintf("Reserving %i of these connections for whitelisted inbound peers\n", nWhiteConnections);
913947
std::ostringstream strErrors;
914948

915949
LogPrintf("Using %u threads for script verification\n", nScriptCheckThreads);

src/net.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ uint64_t nLocalHostNonce = 0;
7979
static std::vector<ListenSocket> vhListenSocket;
8080
CAddrMan addrman;
8181
int nMaxConnections = 125;
82+
int nWhiteConnections = 0;
8283
bool fAddressesInitialized = false;
8384

8485
vector<CNode*> vNodes;
@@ -827,6 +828,7 @@ void ThreadSocketHandler()
827828
SOCKET hSocket = accept(hListenSocket.socket, (struct sockaddr*)&sockaddr, &len);
828829
CAddress addr;
829830
int nInbound = 0;
831+
int nMaxInbound = nMaxConnections - MAX_OUTBOUND_CONNECTIONS;
830832

831833
if (hSocket != INVALID_SOCKET)
832834
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
@@ -846,8 +848,14 @@ void ThreadSocketHandler()
846848
if (nErr != WSAEWOULDBLOCK)
847849
LogPrintf("socket error accept failed: %s\n", NetworkErrorString(nErr));
848850
}
849-
else if (nInbound >= nMaxConnections - MAX_OUTBOUND_CONNECTIONS)
851+
else if (nInbound >= nMaxInbound)
850852
{
853+
LogPrint("net", "connection from %s dropped (full)\n", addr.ToString());
854+
CloseSocket(hSocket);
855+
}
856+
else if (!whitelisted && (nInbound >= (nMaxInbound - nWhiteConnections)))
857+
{
858+
LogPrint("net", "connection from %s dropped (non-whitelisted)\n", addr.ToString());
851859
CloseSocket(hSocket);
852860
}
853861
else if (CNode::IsBanned(addr) && !whitelisted)
@@ -861,6 +869,8 @@ void ThreadSocketHandler()
861869
pnode->AddRef();
862870
pnode->fWhitelisted = whitelisted;
863871

872+
LogPrint("net", "connection from %s accepted\n", addr.ToString());
873+
864874
{
865875
LOCK(cs_vNodes);
866876
vNodes.push_back(pnode);

src/net.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,20 @@ extern bool fListen;
140140
extern uint64_t nLocalServices;
141141
extern uint64_t nLocalHostNonce;
142142
extern CAddrMan addrman;
143+
144+
// The allocation of connections against the maximum allowed (nMaxConnections)
145+
// is prioritized as follows:
146+
// 1st: Outbound connections (MAX_OUTBOUND_CONNECTIONS)
147+
// 2nd: Inbound connections from whitelisted peers (nWhiteConnections)
148+
// 3rd: Inbound connections from non-whitelisted peers
149+
// Thus, the number of connection slots for the general public to use is:
150+
// nMaxConnections - (MAX_OUTBOUND_CONNECTIONS + nWhiteConnections)
151+
// Any additional inbound connections beyond limits will be immediately closed
152+
153+
/** Maximum number of connections to simultaneously allow (aka connection slots) */
143154
extern int nMaxConnections;
155+
/** Number of connection slots to reserve for inbound from whitelisted peers */
156+
extern int nWhiteConnections;
144157

145158
extern std::vector<CNode*> vNodes;
146159
extern CCriticalSection cs_vNodes;

0 commit comments

Comments
 (0)