aboutsummaryrefslogtreecommitdiff
path: root/src/net.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/net.h')
-rw-r--r--src/net.h196
1 files changed, 81 insertions, 115 deletions
diff --git a/src/net.h b/src/net.h
index 6ca402f71d..29b6a44c88 100644
--- a/src/net.h
+++ b/src/net.h
@@ -58,8 +58,10 @@ static const unsigned int MAX_ADDR_TO_SEND = 1000;
static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = 4 * 1000 * 1000;
/** Maximum length of strSubVer in `version` message */
static const unsigned int MAX_SUBVERSION_LENGTH = 256;
-/** Maximum number of outgoing nodes */
+/** Maximum number of automatic outgoing nodes */
static const int MAX_OUTBOUND_CONNECTIONS = 8;
+/** Maximum number of addnode outgoing nodes */
+static const int MAX_ADDNODE_CONNECTIONS = 8;
/** -listen default */
static const bool DEFAULT_LISTEN = true;
/** -upnp default */
@@ -135,6 +137,7 @@ public:
ServiceFlags nRelevantServices = NODE_NONE;
int nMaxConnections = 0;
int nMaxOutbound = 0;
+ int nMaxAddnode = 0;
int nMaxFeeler = 0;
int nBestHeight = 0;
CClientUIInterface* uiInterface = nullptr;
@@ -151,7 +154,7 @@ public:
bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false);
bool GetNetworkActive() const { return fNetworkActive; };
void SetNetworkActive(bool active);
- bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false);
+ bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false, bool fAddnode = false);
bool CheckIncomingNonce(uint64_t nonce);
bool ForNode(NodeId id, std::function<bool(CNode* pnode)> func);
@@ -159,75 +162,33 @@ public:
void PushMessage(CNode* pnode, CSerializedNetMsg&& msg);
template<typename Callable>
- bool ForEachNodeContinueIf(Callable&& func)
- {
- LOCK(cs_vNodes);
- for (auto&& node : vNodes)
- if(!func(node))
- return false;
- return true;
- };
-
- template<typename Callable>
- bool ForEachNodeContinueIf(Callable&& func) const
- {
- LOCK(cs_vNodes);
- for (const auto& node : vNodes)
- if(!func(node))
- return false;
- return true;
- };
-
- template<typename Callable, typename CallableAfter>
- bool ForEachNodeContinueIfThen(Callable&& pre, CallableAfter&& post)
- {
- bool ret = true;
- LOCK(cs_vNodes);
- for (auto&& node : vNodes)
- if(!pre(node)) {
- ret = false;
- break;
- }
- post();
- return ret;
- };
-
- template<typename Callable, typename CallableAfter>
- bool ForEachNodeContinueIfThen(Callable&& pre, CallableAfter&& post) const
- {
- bool ret = true;
- LOCK(cs_vNodes);
- for (const auto& node : vNodes)
- if(!pre(node)) {
- ret = false;
- break;
- }
- post();
- return ret;
- };
-
- template<typename Callable>
void ForEachNode(Callable&& func)
{
LOCK(cs_vNodes);
- for (auto&& node : vNodes)
- func(node);
+ for (auto&& node : vNodes) {
+ if (NodeFullyConnected(node))
+ func(node);
+ }
};
template<typename Callable>
void ForEachNode(Callable&& func) const
{
LOCK(cs_vNodes);
- for (const auto& node : vNodes)
- func(node);
+ for (auto&& node : vNodes) {
+ if (NodeFullyConnected(node))
+ func(node);
+ }
};
template<typename Callable, typename CallableAfter>
void ForEachNodeThen(Callable&& pre, CallableAfter&& post)
{
LOCK(cs_vNodes);
- for (auto&& node : vNodes)
- pre(node);
+ for (auto&& node : vNodes) {
+ if (NodeFullyConnected(node))
+ pre(node);
+ }
post();
};
@@ -235,13 +196,13 @@ public:
void ForEachNodeThen(Callable&& pre, CallableAfter&& post) const
{
LOCK(cs_vNodes);
- for (const auto& node : vNodes)
- pre(node);
+ for (auto&& node : vNodes) {
+ if (NodeFullyConnected(node))
+ pre(node);
+ }
post();
};
- void RelayTransaction(const CTransaction& tx);
-
// Addrman functions
size_t GetAddressCount() const;
void SetServices(const CService &addr, ServiceFlags nServices);
@@ -283,10 +244,8 @@ public:
size_t GetNodeCount(NumConnections num);
void GetNodeStats(std::vector<CNodeStats>& vstats);
- bool DisconnectAddress(const CNetAddr& addr);
bool DisconnectNode(const std::string& node);
bool DisconnectNode(NodeId id);
- bool DisconnectSubnet(const CSubNet& subnet);
unsigned int GetSendBufferSize() const;
@@ -322,8 +281,11 @@ public:
int GetBestHeight() const;
/** Get a unique deterministic randomizer. */
- CSipHasher GetDeterministicRandomizer(uint64_t id);
+ CSipHasher GetDeterministicRandomizer(uint64_t id) const;
+
+ unsigned int GetReceiveFloodSize() const;
+ void WakeMessageHandler();
private:
struct ListenSocket {
SOCKET socket;
@@ -340,7 +302,7 @@ private:
void ThreadSocketHandler();
void ThreadDNSAddressSeed();
- uint64_t CalculateKeyedNetGroup(const CAddress& ad);
+ uint64_t CalculateKeyedNetGroup(const CAddress& ad) const;
CNode* FindNode(const CNetAddr& ip);
CNode* FindNode(const CSubNet& subNet);
@@ -355,6 +317,7 @@ private:
NodeId GetNewNodeId();
+ size_t SocketSendData(CNode *pnode) const;
//!check is the banlist has unwritten changes
bool BannedSetIsDirty();
//!set the "dirty" flag for the banlist
@@ -365,12 +328,13 @@ private:
void DumpData();
void DumpBanlist();
- unsigned int GetReceiveFloodSize() const;
-
// Network stats
void RecordBytesRecv(uint64_t bytes);
void RecordBytesSent(uint64_t bytes);
+ // Whether the node should be passed out in ForEach* callbacks
+ static bool NodeFullyConnected(const CNode* pnode);
+
// Network usage totals
CCriticalSection cs_totalBytesRecv;
CCriticalSection cs_totalBytesSent;
@@ -414,8 +378,10 @@ private:
ServiceFlags nRelevantServices;
CSemaphore *semOutbound;
+ CSemaphore *semAddnode;
int nMaxConnections;
int nMaxOutbound;
+ int nMaxAddnode;
int nMaxFeeler;
std::atomic<int> nBestHeight;
CClientUIInterface* clientInterface;
@@ -423,6 +389,9 @@ private:
/** SipHasher seeds for deterministic randomness */
const uint64_t nSeed0, nSeed1;
+ /** flag for waking the message processor. */
+ bool fMsgProcWake;
+
std::condition_variable condMsgProc;
std::mutex mutexMsgProc;
std::atomic<bool> flagInterruptMsgProc;
@@ -440,7 +409,6 @@ void Discover(boost::thread_group& threadGroup);
void MapPort(bool fUseUPnP);
unsigned short GetListenPort();
bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false);
-size_t SocketSendData(CNode *pnode);
struct CombinerAll
{
@@ -529,6 +497,7 @@ public:
int nVersion;
std::string cleanSubVer;
bool fInbound;
+ bool fAddnode;
int nStartingHeight;
uint64_t nSendBytes;
mapMsgCmdSize mapSendBytesPerMsgCmd;
@@ -595,7 +564,7 @@ class CNode
friend class CConnman;
public:
// socket
- ServiceFlags nServices;
+ std::atomic<ServiceFlags> nServices;
ServiceFlags nServicesExpected;
SOCKET hSocket;
size_t nSendSize; // total size of all vSendMsg entries
@@ -603,32 +572,38 @@ public:
uint64_t nSendBytes;
std::deque<std::vector<unsigned char>> vSendMsg;
CCriticalSection cs_vSend;
+ CCriticalSection cs_hSocket;
+ CCriticalSection cs_vRecv;
+
+ CCriticalSection cs_vProcessMsg;
+ std::list<CNetMessage> vProcessMsg;
+ size_t nProcessQueueSize;
+
+ CCriticalSection cs_sendProcessing;
std::deque<CInv> vRecvGetData;
- std::deque<CNetMessage> vRecvMsg;
- CCriticalSection cs_vRecvMsg;
uint64_t nRecvBytes;
- int nRecvVersion;
+ std::atomic<int> nRecvVersion;
- int64_t nLastSend;
- int64_t nLastRecv;
- int64_t nTimeConnected;
- int64_t nTimeOffset;
+ std::atomic<int64_t> nLastSend;
+ std::atomic<int64_t> nLastRecv;
+ const int64_t nTimeConnected;
+ std::atomic<int64_t> nTimeOffset;
const CAddress addr;
- std::string addrName;
- CService addrLocal;
- int nVersion;
+ std::atomic<int> nVersion;
// strSubVer is whatever byte array we read from the wire. However, this field is intended
// to be printed out, displayed to humans in various forms and so on. So we sanitize it and
// store the sanitized version in cleanSubVer. The original should be used when dealing with
// the network or wire types and the cleaned string used when displayed or logged.
std::string strSubVer, cleanSubVer;
+ CCriticalSection cs_SubVer; // used for both cleanSubVer and strSubVer
bool fWhitelisted; // This peer can bypass DoS banning.
bool fFeeler; // If true this node is being used as a short lived feeler.
bool fOneShot;
+ bool fAddnode;
bool fClient;
const bool fInbound;
- bool fSuccessfullyConnected;
+ std::atomic_bool fSuccessfullyConnected;
std::atomic_bool fDisconnect;
// We use fRelayTxes for two purposes -
// a) it allows us to not relay tx invs before receiving the peer's version message
@@ -639,10 +614,12 @@ public:
CSemaphoreGrant grantOutbound;
CCriticalSection cs_filter;
CBloomFilter* pfilter;
- int nRefCount;
+ std::atomic<int> nRefCount;
const NodeId id;
const uint64_t nKeyedNetGroup;
+ std::atomic_bool fPauseRecv;
+ std::atomic_bool fPauseSend;
protected:
mapMsgCmdSize mapSendBytesPerMsgCmd;
@@ -650,7 +627,7 @@ protected:
public:
uint256 hashContinue;
- int nStartingHeight;
+ std::atomic<int> nStartingHeight;
// flood relay
std::vector<CAddress> vAddrToSend;
@@ -688,15 +665,15 @@ public:
// Ping time measurement:
// The pong reply we're expecting, or 0 if no pong expected.
- uint64_t nPingNonceSent;
+ std::atomic<uint64_t> nPingNonceSent;
// Time (in usec) the last ping was sent, or 0 if no ping was ever sent.
- int64_t nPingUsecStart;
+ std::atomic<int64_t> nPingUsecStart;
// Last measured round-trip time.
- int64_t nPingUsecTime;
+ std::atomic<int64_t> nPingUsecTime;
// Best measured round-trip time.
- int64_t nMinPingUsecTime;
+ std::atomic<int64_t> nMinPingUsecTime;
// Whether a ping is requested.
- bool fPingQueued;
+ std::atomic<bool> fPingQueued;
// Minimum fee rate with which to filter inv's to this node
CAmount minFeeFilter;
CCriticalSection cs_feeFilter;
@@ -716,6 +693,13 @@ private:
const ServiceFlags nLocalServices;
const int nMyStartingHeight;
int nSendVersion;
+ std::list<CNetMessage> vRecvMsg; // Used only by SocketHandler thread
+
+ mutable CCriticalSection cs_addrName;
+ std::string addrName;
+
+ CService addrLocal;
+ mutable CCriticalSection cs_addrLocal;
public:
NodeId GetId() const {
@@ -736,44 +720,22 @@ public:
return nRefCount;
}
- // requires LOCK(cs_vRecvMsg)
- unsigned int GetTotalRecvSize()
- {
- unsigned int total = 0;
- BOOST_FOREACH(const CNetMessage &msg, vRecvMsg)
- total += msg.vRecv.size() + 24;
- return total;
- }
-
- // requires LOCK(cs_vRecvMsg)
bool ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete);
- // requires LOCK(cs_vRecvMsg)
void SetRecvVersion(int nVersionIn)
{
nRecvVersion = nVersionIn;
- BOOST_FOREACH(CNetMessage &msg, vRecvMsg)
- msg.SetVersion(nVersionIn);
}
- void SetSendVersion(int nVersionIn)
+ int GetRecvVersion()
{
- // Send version may only be changed in the version message, and
- // only one version message is allowed per session. We can therefore
- // treat this value as const and even atomic as long as it's only used
- // once the handshake is complete. Any attempt to set this twice is an
- // error.
- assert(nSendVersion == 0);
- nSendVersion = nVersionIn;
+ return nRecvVersion;
}
+ void SetSendVersion(int nVersionIn);
+ int GetSendVersion() const;
- int GetSendVersion() const
- {
- // The send version should always be explicitly set to
- // INIT_PROTO_VERSION rather than using this value until the handshake
- // is complete.
- assert(nSendVersion != 0);
- return nSendVersion;
- }
+ CService GetAddrLocal() const;
+ //! May not be called more than once
+ void SetAddrLocal(const CService& addrLocalIn);
CNode* AddRef()
{
@@ -844,6 +806,10 @@ public:
{
return nLocalServices;
}
+
+ std::string GetAddrName() const;
+ //! Sets the addrName only if it was not previously set
+ void MaybeSetAddrName(const std::string& addrNameIn);
};