diff options
author | Wladimir J. van der Laan <laanwj@gmail.com> | 2016-09-09 11:43:13 +0200 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2016-09-09 11:52:22 +0200 |
commit | 6423116741de2144872389cf63a621539ae79aaa (patch) | |
tree | 88144259eb803a07ce307cdfbddd1723d293b725 /src/net.h | |
parent | 4daf02a03f9ef4b06d7f2198ed7325ae68e117ba (diff) | |
parent | 0103c5b90fa61b5d159a825fcb5a05ca31d0d1c3 (diff) |
Merge #8085: p2p: Begin encapsulation
0103c5b net: move MAX_FEELER_CONNECTIONS into connman (Cory Fields)
e700cd0 Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead (Jeremy Rubin)
d1a2295 Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting (Jeremy Rubin)
98591c5 net: move vNodesDisconnected into CConnman (Cory Fields)
fa2f8bc net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options (Cory Fields)
a19553b net: Introduce CConnection::Options to avoid passing so many params (Cory Fields)
bafa5fc net: Drop StartNode/StopNode and use CConnman directly (Cory Fields)
e81a602 net: pass CClientUIInterface into CConnman (Cory Fields)
f60b905 net: Pass best block known height into CConnman (Cory Fields)
fdf69ff net: move max/max-outbound to CConnman (Cory Fields)
8a59369 net: move semOutbound to CConnman (Cory Fields)
bd72937 net: move nLocalServices/nRelevantServices to CConnman (Cory Fields)
be9c796 net: move SendBufferSize/ReceiveFloodSize to CConnman (Cory Fields)
63cafa6 net: move send/recv statistics to CConnman (Cory Fields)
adf5d4c net: SocketSendData returns written size (Cory Fields)
ee44fa9 net: move messageHandlerCondition to CConnman (Cory Fields)
960cf2e net: move nLocalHostNonce to CConnman (Cory Fields)
551e088 net: move nLastNodeId to CConnman (Cory Fields)
6c19d92 net: move whitelist functions into CConnman (Cory Fields)
53347f0 net: create generic functor accessors and move vNodes to CConnman (Cory Fields)
c0569c7 net: Add most functions needed for vNodes to CConnman (Cory Fields)
8ae2dac net: move added node functions to CConnman (Cory Fields)
502dd3a net: Add oneshot functions to CConnman (Cory Fields)
a0f3d3c net: move ban and addrman functions into CConnman (Cory Fields)
aaf018e net: handle nodesignals in CConnman (Cory Fields)
b1a5f43 net: move OpenNetworkConnection into CConnman (Cory Fields)
02137f1 net: Move socket binding into CConnman (Cory Fields)
5b446dd net: Pass CConnection to wallet rather than using the global (Cory Fields)
8d58c4d net: Pass CConnman around as needed (Cory Fields)
d7349ca net: Add rpc error for missing/disabled p2p functionality (Cory Fields)
cd16f48 net: Create CConnman to encapsulate p2p connections (Cory Fields)
d93b14d net: move CBanDB and CAddrDB out of net.h/cpp (Cory Fields)
531214f gui: add NodeID to the peer table (Cory Fields)
Diffstat (limited to 'src/net.h')
-rw-r--r-- | src/net.h | 544 |
1 files changed, 329 insertions, 215 deletions
@@ -6,6 +6,8 @@ #ifndef BITCOIN_NET_H #define BITCOIN_NET_H +#include "addrdb.h" +#include "addrman.h" #include "amount.h" #include "bloom.h" #include "compat.h" @@ -20,6 +22,7 @@ #include <atomic> #include <deque> #include <stdint.h> +#include <memory> #ifndef WIN32 #include <arpa/inet.h> @@ -51,6 +54,8 @@ 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 */ +static const int MAX_OUTBOUND_CONNECTIONS = 8; /** -listen default */ static const bool DEFAULT_LISTEN = true; /** -upnp default */ @@ -79,25 +84,317 @@ static const ServiceFlags REQUIRED_SERVICES = NODE_NETWORK; // NOTE: When adjusting this, update rpcnet:setban's help ("24h") static const unsigned int DEFAULT_MISBEHAVING_BANTIME = 60 * 60 * 24; // Default 24-hour ban -unsigned int ReceiveFloodSize(); -unsigned int SendBufferSize(); - typedef int NodeId; -void AddOneShot(const std::string& strDest); -void AddressCurrentlyConnected(const CService& addr); -CNode* FindNode(const CNetAddr& ip); -CNode* FindNode(const CSubNet& subNet); -CNode* FindNode(const std::string& addrName); -CNode* FindNode(const CService& ip); -CNode* FindNode(const NodeId id); //TODO: Remove this -bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false); +struct AddedNodeInfo +{ + std::string strAddedNode; + CService resolvedAddress; + bool fConnected; + bool fInbound; +}; + +class CTransaction; +class CNodeStats; +class CClientUIInterface; + +class CConnman +{ +public: + + enum NumConnections { + CONNECTIONS_NONE = 0, + CONNECTIONS_IN = (1U << 0), + CONNECTIONS_OUT = (1U << 1), + CONNECTIONS_ALL = (CONNECTIONS_IN | CONNECTIONS_OUT), + }; + + struct Options + { + ServiceFlags nLocalServices = NODE_NONE; + ServiceFlags nRelevantServices = NODE_NONE; + int nMaxConnections = 0; + int nMaxOutbound = 0; + int nMaxFeeler = 0; + int nBestHeight = 0; + CClientUIInterface* uiInterface = nullptr; + unsigned int nSendBufferMaxSize = 0; + unsigned int nReceiveFloodSize = 0; + }; + CConnman(); + ~CConnman(); + bool Start(boost::thread_group& threadGroup, CScheduler& scheduler, std::string& strNodeError, Options options); + void Stop(); + bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); + bool OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false); + bool CheckIncomingNonce(uint64_t nonce); + + bool ForNode(NodeId id, std::function<bool(CNode* pnode)> func); + + 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); + }; + + template<typename Callable> + void ForEachNode(Callable&& func) const + { + LOCK(cs_vNodes); + for (const auto& node : vNodes) + func(node); + }; + + template<typename Callable, typename CallableAfter> + void ForEachNodeThen(Callable&& pre, CallableAfter&& post) + { + LOCK(cs_vNodes); + for (auto&& node : vNodes) + pre(node); + post(); + }; + + template<typename Callable, typename CallableAfter> + void ForEachNodeThen(Callable&& pre, CallableAfter&& post) const + { + LOCK(cs_vNodes); + for (const auto& node : vNodes) + pre(node); + post(); + }; + + void RelayTransaction(const CTransaction& tx); + + // Addrman functions + size_t GetAddressCount() const; + void SetServices(const CService &addr, ServiceFlags nServices); + void MarkAddressGood(const CAddress& addr); + void AddNewAddress(const CAddress& addr, const CAddress& addrFrom, int64_t nTimePenalty = 0); + void AddNewAddresses(const std::vector<CAddress>& vAddr, const CAddress& addrFrom, int64_t nTimePenalty = 0); + std::vector<CAddress> GetAddresses(); + void AddressCurrentlyConnected(const CService& addr); + + // 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); + void ClearBanned(); // needed for unit testing + 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); + + void AddOneShot(const std::string& strDest); + + bool AddNode(const std::string& node); + bool RemoveAddedNode(const std::string& node); + std::vector<AddedNodeInfo> GetAddedNodeInfo(); + + 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; + + void AddWhitelistedRange(const CSubNet &subnet); + + ServiceFlags GetLocalServices() const; + + //!set the max outbound target in bytes + void SetMaxOutboundTarget(uint64_t limit); + uint64_t GetMaxOutboundTarget(); + + //!set the timeframe for the max outbound target + void SetMaxOutboundTimeframe(uint64_t timeframe); + uint64_t GetMaxOutboundTimeframe(); + + //!check if the outbound target is reached + // if param historicalBlockServingLimit is set true, the function will + // response true if the limit for serving historical blocks has been reached + bool OutboundTargetReached(bool historicalBlockServingLimit); + + //!response the bytes left in the current max outbound cycle + // in case of no limit, it will always response 0 + uint64_t GetOutboundTargetBytesLeft(); + + //!response the time in second left in the current max outbound cycle + // in case of no limit, it will always response 0 + uint64_t GetMaxOutboundTimeLeftInCycle(); + + uint64_t GetTotalBytesRecv(); + uint64_t GetTotalBytesSent(); + + void SetBestHeight(int height); + int GetBestHeight() const; + + +private: + struct ListenSocket { + SOCKET socket; + bool whitelisted; + + ListenSocket(SOCKET socket_, bool whitelisted_) : socket(socket_), whitelisted(whitelisted_) {} + }; + + void ThreadOpenAddedConnections(); + void ProcessOneShot(); + void ThreadOpenConnections(); + void ThreadMessageHandler(); + void AcceptConnection(const ListenSocket& hListenSocket); + void ThreadSocketHandler(); + void ThreadDNSAddressSeed(); + + CNode* FindNode(const CNetAddr& ip); + CNode* FindNode(const CSubNet& subNet); + CNode* FindNode(const std::string& addrName); + CNode* FindNode(const CService& addr); + + bool AttemptToEvictConnection(); + CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure); + bool IsWhitelistedRange(const CNetAddr &addr); + + void DeleteNode(CNode* pnode); + + NodeId GetNewNodeId(); + + //!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 DumpData(); + void DumpBanlist(); + + unsigned int GetReceiveFloodSize() const; + + // Network stats + void RecordBytesRecv(uint64_t bytes); + void RecordBytesSent(uint64_t bytes); + + // Network usage totals + CCriticalSection cs_totalBytesRecv; + CCriticalSection cs_totalBytesSent; + uint64_t nTotalBytesRecv; + uint64_t nTotalBytesSent; + + // outbound limit & stats + uint64_t nMaxOutboundTotalBytesSentInCycle; + uint64_t nMaxOutboundCycleStartTime; + uint64_t nMaxOutboundLimit; + uint64_t nMaxOutboundTimeframe; + + // Whitelisted ranges. Any node connecting from these is automatically + // whitelisted (as well as those connecting to whitelisted binds). + std::vector<CSubNet> vWhitelistedRange; + CCriticalSection cs_vWhitelistedRange; + + unsigned int nSendBufferMaxSize; + unsigned int nReceiveFloodSize; + + std::vector<ListenSocket> vhListenSocket; + banmap_t setBanned; + CCriticalSection cs_setBanned; + bool setBannedIsDirty; + bool fAddressesInitialized; + CAddrMan addrman; + std::deque<std::string> vOneShots; + CCriticalSection cs_vOneShots; + std::vector<std::string> vAddedNodes; + CCriticalSection cs_vAddedNodes; + std::vector<CNode*> vNodes; + std::list<CNode*> vNodesDisconnected; + mutable CCriticalSection cs_vNodes; + std::atomic<NodeId> nLastNodeId; + boost::condition_variable messageHandlerCondition; + + /** Services this instance offers */ + ServiceFlags nLocalServices; + + /** Services this instance cares about */ + ServiceFlags nRelevantServices; + + CSemaphore *semOutbound; + int nMaxConnections; + int nMaxOutbound; + int nMaxFeeler; + std::atomic<int> nBestHeight; + CClientUIInterface* clientInterface; +}; +extern std::unique_ptr<CConnman> g_connman; +void Discover(boost::thread_group& threadGroup); void MapPort(bool fUseUPnP); unsigned short GetListenPort(); bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); -void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler); -bool StopNode(); -void SocketSendData(CNode *pnode); +size_t SocketSendData(CNode *pnode); struct CombinerAll { @@ -117,11 +414,10 @@ struct CombinerAll // Signals for message handling struct CNodeSignals { - boost::signals2::signal<int ()> GetHeight; - boost::signals2::signal<bool (CNode*), CombinerAll> ProcessMessages; - boost::signals2::signal<bool (CNode*), CombinerAll> SendMessages; + boost::signals2::signal<bool (CNode*, CConnman&), CombinerAll> ProcessMessages; + boost::signals2::signal<bool (CNode*, CConnman&), CombinerAll> SendMessages; boost::signals2::signal<void (NodeId, const CNode*)> InitializeNode; - boost::signals2::signal<void (NodeId)> FinalizeNode; + boost::signals2::signal<void (NodeId, bool&)> FinalizeNode; }; @@ -152,30 +448,15 @@ bool IsLocal(const CService& addr); bool GetLocal(CService &addr, const CNetAddr *paddrPeer = NULL); bool IsReachable(enum Network net); bool IsReachable(const CNetAddr &addr); -CAddress GetLocalAddress(const CNetAddr *paddrPeer = NULL); +CAddress GetLocalAddress(const CNetAddr *paddrPeer, ServiceFlags nLocalServices); extern bool fDiscover; extern bool fListen; -extern ServiceFlags nLocalServices; -extern ServiceFlags nRelevantServices; extern bool fRelayTxes; -extern uint64_t nLocalHostNonce; -extern CAddrMan addrman; -/** Maximum number of connections to simultaneously allow (aka connection slots) */ -extern int nMaxConnections; - -extern std::vector<CNode*> vNodes; -extern CCriticalSection cs_vNodes; extern limitedmap<uint256, int64_t> mapAlreadyAskedFor; -extern std::vector<std::string> vAddedNodes; -extern CCriticalSection cs_vAddedNodes; - -extern NodeId nLastNodeId; -extern CCriticalSection cs_nLastNodeId; - /** Subversion as sent to the P2P network in `version` messages */ extern std::string strSubVersion; @@ -256,67 +537,6 @@ public: }; -typedef enum BanReason -{ - BanReasonUnknown = 0, - BanReasonNodeMisbehaving = 1, - BanReasonManuallyAdded = 2 -} BanReason; - -class CBanEntry -{ -public: - static const int CURRENT_VERSION=1; - int nVersion; - int64_t nCreateTime; - int64_t nBanUntil; - uint8_t banReason; - - CBanEntry() - { - SetNull(); - } - - CBanEntry(int64_t nCreateTimeIn) - { - SetNull(); - nCreateTime = nCreateTimeIn; - } - - ADD_SERIALIZE_METHODS; - - template <typename Stream, typename Operation> - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(this->nVersion); - nVersion = this->nVersion; - READWRITE(nCreateTime); - READWRITE(nBanUntil); - READWRITE(banReason); - } - - void SetNull() - { - nVersion = CBanEntry::CURRENT_VERSION; - nCreateTime = 0; - nBanUntil = 0; - banReason = BanReasonUnknown; - } - - std::string banReasonToString() - { - switch (banReason) { - case BanReasonNodeMisbehaving: - return "node misbehaving"; - case BanReasonManuallyAdded: - return "manually added"; - default: - return "unknown"; - } - } -}; - -typedef std::map<CSubNet, CBanEntry> banmap_t; - /** Information about a peer */ class CNode { @@ -328,6 +548,7 @@ public: CDataStream ssSend; size_t nSendSize; // total size of all vSendMsg entries size_t nSendOffset; // offset inside the first vSendMsg already sent + uint64_t nOptimisticBytesWritten; uint64_t nSendBytes; std::deque<CSerializeData> vSendMsg; CCriticalSection cs_vSend; @@ -374,17 +595,6 @@ public: const uint64_t nKeyedNetGroup; protected: - // Denial-of-service detection/prevention - // Key is IP address, value is banned-until-time - static banmap_t setBanned; - static CCriticalSection cs_setBanned; - static bool setBannedIsDirty; - - // Whitelisted ranges. Any node connecting from these is automatically - // whitelisted (as well as those connecting to whitelisted binds). - static std::vector<CSubNet> vWhitelistedRange; - static CCriticalSection cs_vWhitelistedRange; - mapMsgCmdSize mapSendBytesPerMsgCmd; mapMsgCmdSize mapRecvBytesPerMsgCmd; @@ -446,33 +656,28 @@ public: CAmount lastSentFeeFilter; int64_t nextSendTimeFeeFilter; - CNode(SOCKET hSocketIn, const CAddress &addrIn, const std::string &addrNameIn = "", bool fInboundIn = false); + CNode(NodeId id, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress &addrIn, const std::string &addrNameIn = "", bool fInboundIn = false); ~CNode(); private: - // Network usage totals - static CCriticalSection cs_totalBytesRecv; - static CCriticalSection cs_totalBytesSent; - static uint64_t nTotalBytesRecv; - static uint64_t nTotalBytesSent; - - // outbound limit & stats - static uint64_t nMaxOutboundTotalBytesSentInCycle; - static uint64_t nMaxOutboundCycleStartTime; - static uint64_t nMaxOutboundLimit; - static uint64_t nMaxOutboundTimeframe; - CNode(const CNode&); void operator=(const CNode&); static uint64_t CalculateKeyedNetGroup(const CAddress& ad); + uint64_t nLocalHostNonce; + ServiceFlags nLocalServices; + int nMyStartingHeight; public: NodeId GetId() const { return id; } + uint64_t GetLocalNonce() const { + return nLocalHostNonce; + } + int GetRefCount() { assert(nRefCount >= 0); @@ -489,7 +694,7 @@ public: } // requires LOCK(cs_vRecvMsg) - bool ReceiveMsgBytes(const char *pch, unsigned int nBytes); + bool ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete); // requires LOCK(cs_vRecvMsg) void SetRecvVersion(int nVersionIn) @@ -749,110 +954,19 @@ public: void CloseSocketDisconnect(); - // 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. - static void ClearBanned(); // needed for unit testing - static bool IsBanned(CNetAddr ip); - static bool IsBanned(CSubNet subnet); - static void Ban(const CNetAddr &ip, const BanReason &banReason, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false); - static void Ban(const CSubNet &subNet, const BanReason &banReason, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false); - static bool Unban(const CNetAddr &ip); - static bool Unban(const CSubNet &ip); - static void GetBanned(banmap_t &banmap); - static void SetBanned(const banmap_t &banmap); - - //!check is the banlist has unwritten changes - static bool BannedSetIsDirty(); - //!set the "dirty" flag for the banlist - static void SetBannedSetDirty(bool dirty=true); - //!clean unused entries (if bantime has expired) - static void SweepBanned(); - void copyStats(CNodeStats &stats); - static bool IsWhitelistedRange(const CNetAddr &ip); - static void AddWhitelistedRange(const CSubNet &subnet); - - // Network stats - static void RecordBytesRecv(uint64_t bytes); - static void RecordBytesSent(uint64_t bytes); - - static uint64_t GetTotalBytesRecv(); - static uint64_t GetTotalBytesSent(); - - //!set the max outbound target in bytes - static void SetMaxOutboundTarget(uint64_t limit); - static uint64_t GetMaxOutboundTarget(); - - //!set the timeframe for the max outbound target - static void SetMaxOutboundTimeframe(uint64_t timeframe); - static uint64_t GetMaxOutboundTimeframe(); - - //!check if the outbound target is reached - // if param historicalBlockServingLimit is set true, the function will - // response true if the limit for serving historical blocks has been reached - static bool OutboundTargetReached(bool historicalBlockServingLimit); - - //!response the bytes left in the current max outbound cycle - // in case of no limit, it will always response 0 - static uint64_t GetOutboundTargetBytesLeft(); - - //!response the time in second left in the current max outbound cycle - // in case of no limit, it will always response 0 - static uint64_t GetMaxOutboundTimeLeftInCycle(); + ServiceFlags GetLocalServices() const + { + return nLocalServices; + } }; -class CTransaction; -void RelayTransaction(const CTransaction& tx); -/** Access to the (IP) address database (peers.dat) */ -class CAddrDB -{ -private: - boost::filesystem::path pathAddr; -public: - CAddrDB(); - bool Write(const CAddrMan& addr); - bool Read(CAddrMan& addr); - bool Read(CAddrMan& addr, CDataStream& ssPeers); -}; - -/** Access to the banlist database (banlist.dat) */ -class CBanDB -{ -private: - boost::filesystem::path pathBanlist; -public: - CBanDB(); - bool Write(const banmap_t& banSet); - bool Read(banmap_t& banSet); -}; /** Return a timestamp in the future (in microseconds) for exponentially distributed events. */ int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds); -struct AddedNodeInfo -{ - std::string strAddedNode; - CService resolvedAddress; - bool fConnected; - bool fInbound; -}; - -std::vector<AddedNodeInfo> GetAddedNodeInfo(); - #endif // BITCOIN_NET_H |