Changeset View
Changeset View
Standalone View
Standalone View
src/net.h
Show First 20 Lines • Show All 86 Lines • ▼ Show 20 Lines | |||||
static const bool DEFAULT_BLOCKSONLY = false; | static const bool DEFAULT_BLOCKSONLY = false; | ||||
static const bool DEFAULT_FORCEDNSSEED = false; | static const bool DEFAULT_FORCEDNSSEED = false; | ||||
static const size_t DEFAULT_MAXRECEIVEBUFFER = 5 * 1000; | static const size_t DEFAULT_MAXRECEIVEBUFFER = 5 * 1000; | ||||
static const size_t DEFAULT_MAXSENDBUFFER = 1 * 1000; | static const size_t DEFAULT_MAXSENDBUFFER = 1 * 1000; | ||||
// Default 24-hour ban. | // Default 24-hour ban. | ||||
// NOTE: When adjusting this, update rpcnet:setban's help ("24h") | // NOTE: When adjusting this, update rpcnet:setban's help ("24h") | ||||
static const unsigned int DEFAULT_MISBEHAVING_BANTIME = 60 * 60 * 24; | static constexpr unsigned int DEFAULT_MISBEHAVING_BANTIME = 60 * 60 * 24; | ||||
typedef int64_t NodeId; | typedef int64_t NodeId; | ||||
struct AddedNodeInfo { | struct AddedNodeInfo { | ||||
std::string strAddedNode; | std::string strAddedNode; | ||||
CService resolvedAddress; | CService resolvedAddress; | ||||
bool fConnected; | bool fConnected; | ||||
bool fInbound; | bool fInbound; | ||||
Show All 9 Lines | struct CSerializedNetMsg { | ||||
// No copying, only moves. | // No copying, only moves. | ||||
CSerializedNetMsg(const CSerializedNetMsg &msg) = delete; | CSerializedNetMsg(const CSerializedNetMsg &msg) = delete; | ||||
CSerializedNetMsg &operator=(const CSerializedNetMsg &) = delete; | CSerializedNetMsg &operator=(const CSerializedNetMsg &) = delete; | ||||
std::vector<uint8_t> data; | std::vector<uint8_t> data; | ||||
std::string command; | std::string command; | ||||
}; | }; | ||||
class BanMan { | |||||
public: | |||||
// Denial-of-service detection/prevention | |||||
// The idea is to detect peers that are behaving | |||||
// badly and disconnect/ban them, but do it in a | |||||
// one-coding-mistake-won't-shatter-the-entire-network | |||||
// way. | |||||
// IMPORTANT: There should be nothing I can give a | |||||
// node that it will forward on that will make that | |||||
// node's peers drop it. If there is, an attacker | |||||
// can isolate a node and/or try to split the network. | |||||
// Dropping a node for sending stuff that is invalid | |||||
// now but might be valid in a later version is also | |||||
// dangerous, because it can cause a network split | |||||
// between nodes running old code and nodes running | |||||
// new code. | |||||
~BanMan(); | |||||
BanMan(const CChainParams &_params, CClientUIInterface *client_interface); | |||||
void Ban(const CNetAddr &netAddr, const BanReason &reason, | |||||
int64_t bantimeoffset = 0, bool sinceUnixEpoch = false); | |||||
void Ban(const CSubNet &subNet, const BanReason &reason, | |||||
int64_t bantimeoffset = 0, bool sinceUnixEpoch = false); | |||||
// needed for unit testing | |||||
void ClearBanned(); | |||||
bool IsBanned(CNetAddr ip); | |||||
bool IsBanned(CSubNet subnet); | |||||
bool Unban(const CNetAddr &ip); | |||||
bool Unban(const CSubNet &ip); | |||||
void GetBanned(banmap_t &banmap); | |||||
void DumpBanlist(); | |||||
private: | |||||
void SetBanned(const banmap_t &banmap); | |||||
bool BannedSetIsDirty(); | |||||
//! set the "dirty" flag for the banlist | |||||
void SetBannedSetDirty(bool dirty = true); | |||||
//! clean unused entries (if bantime has expired) | |||||
void SweepBanned(); | |||||
banmap_t setBanned; | |||||
CCriticalSection cs_setBanned; | |||||
bool setBannedIsDirty; | |||||
CClientUIInterface *clientInterface = nullptr; | |||||
const CChainParams ¶ms; | |||||
}; | |||||
class NetEventsInterface; | class NetEventsInterface; | ||||
class CConnman { | class CConnman { | ||||
public: | public: | ||||
enum NumConnections { | enum NumConnections { | ||||
CONNECTIONS_NONE = 0, | CONNECTIONS_NONE = 0, | ||||
CONNECTIONS_IN = (1U << 0), | CONNECTIONS_IN = (1U << 0), | ||||
CONNECTIONS_OUT = (1U << 1), | CONNECTIONS_OUT = (1U << 1), | ||||
CONNECTIONS_ALL = (CONNECTIONS_IN | CONNECTIONS_OUT), | CONNECTIONS_ALL = (CONNECTIONS_IN | CONNECTIONS_OUT), | ||||
}; | }; | ||||
struct Options { | struct Options { | ||||
ServiceFlags nLocalServices = NODE_NONE; | ServiceFlags nLocalServices = NODE_NONE; | ||||
int nMaxConnections = 0; | int nMaxConnections = 0; | ||||
int nMaxOutbound = 0; | int nMaxOutbound = 0; | ||||
int nMaxAddnode = 0; | int nMaxAddnode = 0; | ||||
int nMaxFeeler = 0; | int nMaxFeeler = 0; | ||||
int nBestHeight = 0; | int nBestHeight = 0; | ||||
CClientUIInterface *uiInterface = nullptr; | CClientUIInterface *uiInterface = nullptr; | ||||
NetEventsInterface *m_msgproc = nullptr; | NetEventsInterface *m_msgproc = nullptr; | ||||
BanMan *m_banman = nullptr; | |||||
unsigned int nSendBufferMaxSize = 0; | unsigned int nSendBufferMaxSize = 0; | ||||
unsigned int nReceiveFloodSize = 0; | unsigned int nReceiveFloodSize = 0; | ||||
uint64_t nMaxOutboundTimeframe = 0; | uint64_t nMaxOutboundTimeframe = 0; | ||||
uint64_t nMaxOutboundLimit = 0; | uint64_t nMaxOutboundLimit = 0; | ||||
std::vector<std::string> vSeedNodes; | std::vector<std::string> vSeedNodes; | ||||
std::vector<CSubNet> vWhitelistedRange; | std::vector<CSubNet> vWhitelistedRange; | ||||
std::vector<CService> vBinds, vWhiteBinds; | std::vector<CService> vBinds, vWhiteBinds; | ||||
bool m_use_addrman_outgoing = true; | bool m_use_addrman_outgoing = true; | ||||
std::vector<std::string> m_specified_outgoing; | std::vector<std::string> m_specified_outgoing; | ||||
std::vector<std::string> m_added_nodes; | std::vector<std::string> m_added_nodes; | ||||
}; | }; | ||||
void Init(const Options &connOptions) { | void Init(const Options &connOptions) { | ||||
nLocalServices = connOptions.nLocalServices; | nLocalServices = connOptions.nLocalServices; | ||||
nMaxConnections = connOptions.nMaxConnections; | nMaxConnections = connOptions.nMaxConnections; | ||||
nMaxOutbound = | nMaxOutbound = | ||||
std::min(connOptions.nMaxOutbound, connOptions.nMaxConnections); | std::min(connOptions.nMaxOutbound, connOptions.nMaxConnections); | ||||
nMaxAddnode = connOptions.nMaxAddnode; | nMaxAddnode = connOptions.nMaxAddnode; | ||||
nMaxFeeler = connOptions.nMaxFeeler; | nMaxFeeler = connOptions.nMaxFeeler; | ||||
nBestHeight = connOptions.nBestHeight; | nBestHeight = connOptions.nBestHeight; | ||||
clientInterface = connOptions.uiInterface; | clientInterface = connOptions.uiInterface; | ||||
m_banman = connOptions.m_banman; | |||||
m_msgproc = connOptions.m_msgproc; | m_msgproc = connOptions.m_msgproc; | ||||
nSendBufferMaxSize = connOptions.nSendBufferMaxSize; | nSendBufferMaxSize = connOptions.nSendBufferMaxSize; | ||||
nReceiveFloodSize = connOptions.nReceiveFloodSize; | nReceiveFloodSize = connOptions.nReceiveFloodSize; | ||||
{ | { | ||||
LOCK(cs_totalBytesSent); | LOCK(cs_totalBytesSent); | ||||
nMaxOutboundTimeframe = connOptions.nMaxOutboundTimeframe; | nMaxOutboundTimeframe = connOptions.nMaxOutboundTimeframe; | ||||
nMaxOutboundLimit = connOptions.nMaxOutboundLimit; | nMaxOutboundLimit = connOptions.nMaxOutboundLimit; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | public: | ||||
// Addrman functions | // Addrman functions | ||||
size_t GetAddressCount() const; | size_t GetAddressCount() const; | ||||
void SetServices(const CService &addr, ServiceFlags nServices); | void SetServices(const CService &addr, ServiceFlags nServices); | ||||
void MarkAddressGood(const CAddress &addr); | void MarkAddressGood(const CAddress &addr); | ||||
void AddNewAddresses(const std::vector<CAddress> &vAddr, | void AddNewAddresses(const std::vector<CAddress> &vAddr, | ||||
const CAddress &addrFrom, int64_t nTimePenalty = 0); | const CAddress &addrFrom, int64_t nTimePenalty = 0); | ||||
std::vector<CAddress> GetAddresses(); | std::vector<CAddress> GetAddresses(); | ||||
// Denial-of-service detection/prevention. The idea is to detect peers that | |||||
// are behaving badly and disconnect/ban them, but do it in a | |||||
// one-coding-mistake-won't-shatter-the-entire-network way. | |||||
// IMPORTANT: There should be nothing I can give a node that it will forward | |||||
// on that will make that node's peers drop it. If there is, an attacker can | |||||
// isolate a node and/or try to split the network. Dropping a node for | |||||
// sending stuff that is invalid now but might be valid in a later version | |||||
// is also dangerous, because it can cause a network split between nodes | |||||
// running old code and nodes running new code. | |||||
void Ban(const CNetAddr &netAddr, const BanReason &reason, | |||||
int64_t bantimeoffset = 0, bool sinceUnixEpoch = false); | |||||
void Ban(const CSubNet &subNet, const BanReason &reason, | |||||
int64_t bantimeoffset = 0, bool sinceUnixEpoch = false); | |||||
// Needed for unit testing. | |||||
void ClearBanned(); | |||||
bool IsBanned(CNetAddr ip); | |||||
bool IsBanned(CSubNet subnet); | |||||
bool Unban(const CNetAddr &ip); | |||||
bool Unban(const CSubNet &ip); | |||||
void GetBanned(banmap_t &banmap); | |||||
void SetBanned(const banmap_t &banmap); | |||||
// This allows temporarily exceeding nMaxOutbound, with the goal of finding | // This allows temporarily exceeding nMaxOutbound, with the goal of finding | ||||
// a peer that is better than all our current peers. | // a peer that is better than all our current peers. | ||||
void SetTryNewOutboundPeer(bool flag); | void SetTryNewOutboundPeer(bool flag); | ||||
bool GetTryNewOutboundPeer(); | bool GetTryNewOutboundPeer(); | ||||
// Return the number of outbound peers we have in excess of our target (eg, | // Return the number of outbound peers we have in excess of our target (eg, | ||||
// if we previously called SetTryNewOutboundPeer(true), and have since set | // if we previously called SetTryNewOutboundPeer(true), and have since set | ||||
// to false, we may have extra peers that we wish to disconnect). This may | // to false, we may have extra peers that we wish to disconnect). This may | ||||
▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | CNode *ConnectNode(CAddress addrConnect, const char *pszDest, | ||||
bool fCountFailure, bool manual_connection); | bool fCountFailure, bool manual_connection); | ||||
bool IsWhitelistedRange(const CNetAddr &addr); | bool IsWhitelistedRange(const CNetAddr &addr); | ||||
void DeleteNode(CNode *pnode); | void DeleteNode(CNode *pnode); | ||||
NodeId GetNewNodeId(); | NodeId GetNewNodeId(); | ||||
size_t SocketSendData(CNode *pnode) const; | size_t SocketSendData(CNode *pnode) const; | ||||
//! check is the banlist has unwritten changes | |||||
bool BannedSetIsDirty(); | |||||
//! set the "dirty" flag for the banlist | |||||
void SetBannedSetDirty(bool dirty = true); | |||||
//! clean unused entries (if bantime has expired) | |||||
void SweepBanned(); | |||||
void DumpAddresses(); | void DumpAddresses(); | ||||
void DumpData(); | |||||
void DumpBanlist(); | |||||
// Network stats | // Network stats | ||||
void RecordBytesRecv(uint64_t bytes); | void RecordBytesRecv(uint64_t bytes); | ||||
void RecordBytesSent(uint64_t bytes); | void RecordBytesSent(uint64_t bytes); | ||||
// Whether the node should be passed out in ForEach* callbacks | // Whether the node should be passed out in ForEach* callbacks | ||||
static bool NodeFullyConnected(const CNode *pnode); | static bool NodeFullyConnected(const CNode *pnode); | ||||
Show All 15 Lines | private: | ||||
// whitelisted (as well as those connecting to whitelisted binds). | // whitelisted (as well as those connecting to whitelisted binds). | ||||
std::vector<CSubNet> vWhitelistedRange; | std::vector<CSubNet> vWhitelistedRange; | ||||
unsigned int nSendBufferMaxSize{0}; | unsigned int nSendBufferMaxSize{0}; | ||||
unsigned int nReceiveFloodSize{0}; | unsigned int nReceiveFloodSize{0}; | ||||
std::vector<ListenSocket> vhListenSocket; | std::vector<ListenSocket> vhListenSocket; | ||||
std::atomic<bool> fNetworkActive{true}; | std::atomic<bool> fNetworkActive{true}; | ||||
banmap_t setBanned GUARDED_BY(cs_setBanned); | |||||
CCriticalSection cs_setBanned; | |||||
bool setBannedIsDirty GUARDED_BY(cs_setBanned){false}; | |||||
bool fAddressesInitialized{false}; | bool fAddressesInitialized{false}; | ||||
CAddrMan addrman; | CAddrMan addrman; | ||||
std::deque<std::string> vOneShots GUARDED_BY(cs_vOneShots); | std::deque<std::string> vOneShots GUARDED_BY(cs_vOneShots); | ||||
CCriticalSection cs_vOneShots; | CCriticalSection cs_vOneShots; | ||||
std::vector<std::string> vAddedNodes GUARDED_BY(cs_vAddedNodes); | std::vector<std::string> vAddedNodes GUARDED_BY(cs_vAddedNodes); | ||||
CCriticalSection cs_vAddedNodes; | CCriticalSection cs_vAddedNodes; | ||||
std::vector<CNode *> vNodes; | std::vector<CNode *> vNodes; | ||||
std::list<CNode *> vNodesDisconnected; | std::list<CNode *> vNodesDisconnected; | ||||
mutable CCriticalSection cs_vNodes; | mutable CCriticalSection cs_vNodes; | ||||
std::atomic<NodeId> nLastNodeId{0}; | std::atomic<NodeId> nLastNodeId{0}; | ||||
unsigned int nPrevNodeCount{0}; | unsigned int nPrevNodeCount{0}; | ||||
/** Services this instance offers */ | /** Services this instance offers */ | ||||
ServiceFlags nLocalServices; | ServiceFlags nLocalServices; | ||||
std::unique_ptr<CSemaphore> semOutbound; | std::unique_ptr<CSemaphore> semOutbound; | ||||
std::unique_ptr<CSemaphore> semAddnode; | std::unique_ptr<CSemaphore> semAddnode; | ||||
int nMaxConnections; | int nMaxConnections; | ||||
int nMaxOutbound; | int nMaxOutbound; | ||||
int nMaxAddnode; | int nMaxAddnode; | ||||
int nMaxFeeler; | int nMaxFeeler; | ||||
std::atomic<int> nBestHeight; | std::atomic<int> nBestHeight; | ||||
CClientUIInterface *clientInterface; | CClientUIInterface *clientInterface; | ||||
NetEventsInterface *m_msgproc; | NetEventsInterface *m_msgproc; | ||||
BanMan *m_banman; | |||||
/** SipHasher seeds for deterministic randomness */ | /** SipHasher seeds for deterministic randomness */ | ||||
const uint64_t nSeed0, nSeed1; | const uint64_t nSeed0, nSeed1; | ||||
/** flag for waking the message processor. */ | /** flag for waking the message processor. */ | ||||
bool fMsgProcWake; | bool fMsgProcWake; | ||||
std::condition_variable condMsgProc; | std::condition_variable condMsgProc; | ||||
Show All 14 Lines | private: | ||||
* This takes the place of a feeler connection. | * This takes the place of a feeler connection. | ||||
*/ | */ | ||||
std::atomic_bool m_try_another_outbound_peer; | std::atomic_bool m_try_another_outbound_peer; | ||||
friend struct CConnmanTest; | friend struct CConnmanTest; | ||||
}; | }; | ||||
extern std::unique_ptr<CConnman> g_connman; | extern std::unique_ptr<CConnman> g_connman; | ||||
extern std::unique_ptr<BanMan> g_banman; | |||||
void Discover(); | void Discover(); | ||||
void StartMapPort(); | void StartMapPort(); | ||||
void InterruptMapPort(); | void InterruptMapPort(); | ||||
void StopMapPort(); | void StopMapPort(); | ||||
unsigned short GetListenPort(); | unsigned short GetListenPort(); | ||||
bool BindListenPort(const CService &bindAddr, std::string &strError, | bool BindListenPort(const CService &bindAddr, std::string &strError, | ||||
bool fWhitelisted = false); | bool fWhitelisted = false); | ||||
▲ Show 20 Lines • Show All 409 Lines • Show Last 20 Lines |