r1
This commit is contained in:
@@ -0,0 +1,772 @@
|
||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Copyright (c) 2015-2019 The PIVX developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_NET_H
|
||||
#define BITCOIN_NET_H
|
||||
|
||||
#include "bloom.h"
|
||||
#include "compat.h"
|
||||
#include "hash.h"
|
||||
#include "limitedmap.h"
|
||||
#include "mruset.h"
|
||||
#include "netbase.h"
|
||||
#include "protocol.h"
|
||||
#include "random.h"
|
||||
#include "streams.h"
|
||||
#include "sync.h"
|
||||
#include "uint256.h"
|
||||
#include "utilstrencodings.h"
|
||||
|
||||
#include <deque>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/signals2/signal.hpp>
|
||||
|
||||
class CAddrMan;
|
||||
class CBlockIndex;
|
||||
class CScheduler;
|
||||
class CNode;
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class thread_group;
|
||||
} // namespace boost
|
||||
|
||||
/** Time between pings automatically sent out for latency probing and keepalive (in seconds). */
|
||||
static const int PING_INTERVAL = 2 * 60;
|
||||
/** Time after which to disconnect, after waiting for a ping response (or inactivity). */
|
||||
static const int TIMEOUT_INTERVAL = 20 * 60;
|
||||
/** The maximum number of entries in an 'inv' protocol message */
|
||||
static const unsigned int MAX_INV_SZ = 50000;
|
||||
/** The maximum number of new addresses to accumulate before announcing. */
|
||||
static const unsigned int MAX_ADDR_TO_SEND = 1000;
|
||||
/** Maximum length of incoming protocol messages (no message over 2 MiB is currently acceptable). */
|
||||
static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = 2 * 1024 * 1024;
|
||||
/** Maximum length of strSubVer in `version` message */
|
||||
static const unsigned int MAX_SUBVERSION_LENGTH = 256;
|
||||
/** -listen default */
|
||||
static const bool DEFAULT_LISTEN = true;
|
||||
/** -upnp default */
|
||||
#ifdef USE_UPNP
|
||||
static const bool DEFAULT_UPNP = USE_UPNP;
|
||||
#else
|
||||
static const bool DEFAULT_UPNP = false;
|
||||
#endif
|
||||
/** The maximum number of entries in mapAskFor */
|
||||
static const size_t MAPASKFOR_MAX_SZ = MAX_INV_SZ;
|
||||
|
||||
unsigned int ReceiveFloodSize();
|
||||
unsigned int SendBufferSize();
|
||||
|
||||
void AddOneShot(std::string strDest);
|
||||
bool RecvLine(SOCKET hSocket, std::string& strLine);
|
||||
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* ConnectNode(CAddress addrConnect, const char* pszDest = NULL, bool obfuScationMaster = false);
|
||||
bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant* grantOutbound = NULL, const char* strDest = NULL, bool fOneShot = false);
|
||||
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);
|
||||
|
||||
typedef int NodeId;
|
||||
|
||||
// Signals for message handling
|
||||
struct CNodeSignals {
|
||||
boost::signals2::signal<int()> GetHeight;
|
||||
boost::signals2::signal<bool(CNode*)> ProcessMessages;
|
||||
boost::signals2::signal<bool(CNode*, bool)> SendMessages;
|
||||
boost::signals2::signal<void(NodeId, const CNode*)> InitializeNode;
|
||||
boost::signals2::signal<void(NodeId)> FinalizeNode;
|
||||
};
|
||||
|
||||
|
||||
CNodeSignals& GetNodeSignals();
|
||||
|
||||
|
||||
enum {
|
||||
LOCAL_NONE, // unknown
|
||||
LOCAL_IF, // address a local interface listens on
|
||||
LOCAL_BIND, // address explicit bound to
|
||||
LOCAL_UPNP, // address reported by UPnP
|
||||
LOCAL_MANUAL, // address explicitly specified (-externalip=)
|
||||
|
||||
LOCAL_MAX
|
||||
};
|
||||
|
||||
bool IsPeerAddrLocalGood(CNode* pnode);
|
||||
void AdvertizeLocal(CNode* pnode);
|
||||
void SetLimited(enum Network net, bool fLimited = true);
|
||||
bool IsLimited(enum Network net);
|
||||
bool IsLimited(const CNetAddr& addr);
|
||||
bool AddLocal(const CService& addr, int nScore = LOCAL_NONE);
|
||||
bool AddLocal(const CNetAddr& addr, int nScore = LOCAL_NONE);
|
||||
bool RemoveLocal(const CService& addr);
|
||||
bool SeenLocal(const CService& addr);
|
||||
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);
|
||||
|
||||
|
||||
extern bool fDiscover;
|
||||
extern bool fListen;
|
||||
extern uint64_t nLocalServices;
|
||||
extern uint64_t nLocalHostNonce;
|
||||
extern CAddrMan addrman;
|
||||
extern int nMaxConnections;
|
||||
|
||||
extern std::vector<CNode*> vNodes;
|
||||
extern CCriticalSection cs_vNodes;
|
||||
extern std::map<CInv, CDataStream> mapRelay;
|
||||
extern std::deque<std::pair<int64_t, CInv> > vRelayExpiration;
|
||||
extern CCriticalSection cs_mapRelay;
|
||||
extern limitedmap<CInv, 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;
|
||||
|
||||
struct LocalServiceInfo {
|
||||
int nScore;
|
||||
int nPort;
|
||||
};
|
||||
|
||||
extern CCriticalSection cs_mapLocalHost;
|
||||
extern std::map<CNetAddr, LocalServiceInfo> mapLocalHost;
|
||||
|
||||
class CNodeStats
|
||||
{
|
||||
public:
|
||||
NodeId nodeid;
|
||||
uint64_t nServices;
|
||||
int64_t nLastSend;
|
||||
int64_t nLastRecv;
|
||||
int64_t nTimeConnected;
|
||||
int64_t nTimeOffset;
|
||||
std::string addrName;
|
||||
int nVersion;
|
||||
std::string cleanSubVer;
|
||||
bool fInbound;
|
||||
int nStartingHeight;
|
||||
uint64_t nSendBytes;
|
||||
uint64_t nRecvBytes;
|
||||
bool fWhitelisted;
|
||||
double dPingTime;
|
||||
double dPingWait;
|
||||
std::string addrLocal;
|
||||
};
|
||||
|
||||
|
||||
class CNetMessage
|
||||
{
|
||||
public:
|
||||
bool in_data; // parsing header (false) or data (true)
|
||||
|
||||
CDataStream hdrbuf; // partially received header
|
||||
CMessageHeader hdr; // complete header
|
||||
unsigned int nHdrPos;
|
||||
|
||||
CDataStream vRecv; // received message data
|
||||
unsigned int nDataPos;
|
||||
|
||||
int64_t nTime; // time (in microseconds) of message receipt.
|
||||
|
||||
CNetMessage(int nTypeIn, int nVersionIn) : hdrbuf(nTypeIn, nVersionIn), vRecv(nTypeIn, nVersionIn)
|
||||
{
|
||||
hdrbuf.resize(24);
|
||||
in_data = false;
|
||||
nHdrPos = 0;
|
||||
nDataPos = 0;
|
||||
nTime = 0;
|
||||
}
|
||||
|
||||
bool complete() const
|
||||
{
|
||||
if (!in_data)
|
||||
return false;
|
||||
return (hdr.nMessageSize == nDataPos);
|
||||
}
|
||||
|
||||
void SetVersion(int nVersionIn)
|
||||
{
|
||||
hdrbuf.SetVersion(nVersionIn);
|
||||
vRecv.SetVersion(nVersionIn);
|
||||
}
|
||||
|
||||
int readHeader(const char* pch, unsigned int nBytes);
|
||||
int readData(const char* pch, unsigned int nBytes);
|
||||
};
|
||||
|
||||
|
||||
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
|
||||
{
|
||||
public:
|
||||
// socket
|
||||
uint64_t nServices;
|
||||
SOCKET hSocket;
|
||||
CDataStream ssSend;
|
||||
size_t nSendSize; // total size of all vSendMsg entries
|
||||
size_t nSendOffset; // offset inside the first vSendMsg already sent
|
||||
uint64_t nSendBytes;
|
||||
std::deque<CSerializeData> vSendMsg;
|
||||
CCriticalSection cs_vSend;
|
||||
|
||||
std::deque<CInv> vRecvGetData;
|
||||
std::deque<CNetMessage> vRecvMsg;
|
||||
CCriticalSection cs_vRecvMsg;
|
||||
uint64_t nRecvBytes;
|
||||
int nRecvVersion;
|
||||
|
||||
int64_t nLastSend;
|
||||
int64_t nLastRecv;
|
||||
int64_t nTimeConnected;
|
||||
int64_t nTimeOffset;
|
||||
CAddress addr;
|
||||
std::string addrName;
|
||||
CService addrLocal;
|
||||
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;
|
||||
bool fWhitelisted; // This peer can bypass DoS banning.
|
||||
bool fOneShot;
|
||||
bool fClient;
|
||||
bool fInbound;
|
||||
bool fNetworkNode;
|
||||
bool fSuccessfullyConnected;
|
||||
bool fDisconnect;
|
||||
// We use fRelayTxes for two purposes -
|
||||
// a) it allows us to not relay tx invs before receiving the peer's version message
|
||||
// b) the peer may tell us in their version message that we should not relay tx invs
|
||||
// until they have initialized their bloom filter.
|
||||
bool fRelayTxes;
|
||||
// Should be 'true' only if we connected to this node to actually mix funds.
|
||||
// In this case node will be released automatically via CMasternodeMan::ProcessMasternodeConnections().
|
||||
// Connecting to verify connectability/status or connecting for sending/relaying single message
|
||||
// (even if it's relative to mixing e.g. for blinding) should NOT set this to 'true'.
|
||||
// For such cases node should be released manually (preferably right after corresponding code).
|
||||
bool fObfuScationMaster;
|
||||
CSemaphoreGrant grantOutbound;
|
||||
CCriticalSection cs_filter;
|
||||
CBloomFilter* pfilter;
|
||||
int nRefCount;
|
||||
NodeId id;
|
||||
|
||||
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;
|
||||
|
||||
std::vector<std::string> vecRequestsFulfilled; //keep track of what client has asked for
|
||||
|
||||
// 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;
|
||||
|
||||
// Basic fuzz-testing
|
||||
void Fuzz(int nChance); // modifies ssSend
|
||||
|
||||
public:
|
||||
uint256 hashContinue;
|
||||
int nStartingHeight;
|
||||
|
||||
// flood relay
|
||||
std::vector<CAddress> vAddrToSend;
|
||||
mruset<CAddress> setAddrKnown;
|
||||
bool fGetAddr;
|
||||
std::set<uint256> setKnown;
|
||||
|
||||
// inventory based relay
|
||||
mruset<CInv> setInventoryKnown;
|
||||
std::vector<CInv> vInventoryToSend;
|
||||
CCriticalSection cs_inventory;
|
||||
std::multimap<int64_t, CInv> mapAskFor;
|
||||
std::vector<uint256> vBlockRequested;
|
||||
|
||||
// Ping time measurement:
|
||||
// The pong reply we're expecting, or 0 if no pong expected.
|
||||
uint64_t nPingNonceSent;
|
||||
// Time (in usec) the last ping was sent, or 0 if no ping was ever sent.
|
||||
int64_t nPingUsecStart;
|
||||
// Last measured round-trip time.
|
||||
int64_t nPingUsecTime;
|
||||
// Whether a ping is requested.
|
||||
bool fPingQueued;
|
||||
|
||||
CNode(SOCKET hSocketIn, CAddress addrIn, 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;
|
||||
|
||||
CNode(const CNode&);
|
||||
void operator=(const CNode&);
|
||||
|
||||
public:
|
||||
NodeId GetId() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
int GetRefCount()
|
||||
{
|
||||
assert(nRefCount >= 0);
|
||||
return nRefCount;
|
||||
}
|
||||
|
||||
// requires LOCK(cs_vRecvMsg)
|
||||
unsigned int GetTotalRecvSize()
|
||||
{
|
||||
unsigned int total = 0;
|
||||
for (const CNetMessage& msg : vRecvMsg)
|
||||
total += msg.vRecv.size() + 24;
|
||||
return total;
|
||||
}
|
||||
|
||||
// requires LOCK(cs_vRecvMsg)
|
||||
bool ReceiveMsgBytes(const char* pch, unsigned int nBytes);
|
||||
|
||||
// requires LOCK(cs_vRecvMsg)
|
||||
void SetRecvVersion(int nVersionIn)
|
||||
{
|
||||
nRecvVersion = nVersionIn;
|
||||
for (CNetMessage& msg : vRecvMsg)
|
||||
msg.SetVersion(nVersionIn);
|
||||
}
|
||||
|
||||
CNode* AddRef()
|
||||
{
|
||||
nRefCount++;
|
||||
return this;
|
||||
}
|
||||
|
||||
void Release()
|
||||
{
|
||||
nRefCount--;
|
||||
}
|
||||
|
||||
|
||||
void AddAddressKnown(const CAddress& addr)
|
||||
{
|
||||
setAddrKnown.insert(addr);
|
||||
}
|
||||
|
||||
void PushAddress(const CAddress& addr)
|
||||
{
|
||||
// Known checking here is only to save space from duplicates.
|
||||
// SendMessages will filter it again for knowns that were added
|
||||
// after addresses were pushed.
|
||||
if (addr.IsValid() && !setAddrKnown.count(addr)) {
|
||||
if (vAddrToSend.size() >= MAX_ADDR_TO_SEND) {
|
||||
vAddrToSend[insecure_rand() % vAddrToSend.size()] = addr;
|
||||
} else {
|
||||
vAddrToSend.push_back(addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AddInventoryKnown(const CInv& inv)
|
||||
{
|
||||
{
|
||||
LOCK(cs_inventory);
|
||||
setInventoryKnown.insert(inv);
|
||||
}
|
||||
}
|
||||
|
||||
void PushInventory(const CInv& inv)
|
||||
{
|
||||
{
|
||||
LOCK(cs_inventory);
|
||||
if (!setInventoryKnown.count(inv))
|
||||
vInventoryToSend.push_back(inv);
|
||||
}
|
||||
}
|
||||
|
||||
void AskFor(const CInv& inv);
|
||||
|
||||
// TODO: Document the postcondition of this function. Is cs_vSend locked?
|
||||
void BeginMessage(const char* pszCommand) EXCLUSIVE_LOCK_FUNCTION(cs_vSend);
|
||||
|
||||
// TODO: Document the precondition of this function. Is cs_vSend locked?
|
||||
void AbortMessage() UNLOCK_FUNCTION(cs_vSend);
|
||||
|
||||
// TODO: Document the precondition of this function. Is cs_vSend locked?
|
||||
void EndMessage() UNLOCK_FUNCTION(cs_vSend);
|
||||
|
||||
void PushVersion();
|
||||
|
||||
|
||||
void PushMessage(const char* pszCommand)
|
||||
{
|
||||
try {
|
||||
BeginMessage(pszCommand);
|
||||
EndMessage();
|
||||
} catch (...) {
|
||||
AbortMessage();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1>
|
||||
void PushMessage(const char* pszCommand, const T1& a1)
|
||||
{
|
||||
try {
|
||||
BeginMessage(pszCommand);
|
||||
ssSend << a1;
|
||||
EndMessage();
|
||||
} catch (...) {
|
||||
AbortMessage();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
void PushMessage(const char* pszCommand, const T1& a1, const T2& a2)
|
||||
{
|
||||
try {
|
||||
BeginMessage(pszCommand);
|
||||
ssSend << a1 << a2;
|
||||
EndMessage();
|
||||
} catch (...) {
|
||||
AbortMessage();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3>
|
||||
void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3)
|
||||
{
|
||||
try {
|
||||
BeginMessage(pszCommand);
|
||||
ssSend << a1 << a2 << a3;
|
||||
EndMessage();
|
||||
} catch (...) {
|
||||
AbortMessage();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4>
|
||||
void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4)
|
||||
{
|
||||
try {
|
||||
BeginMessage(pszCommand);
|
||||
ssSend << a1 << a2 << a3 << a4;
|
||||
EndMessage();
|
||||
} catch (...) {
|
||||
AbortMessage();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5)
|
||||
{
|
||||
try {
|
||||
BeginMessage(pszCommand);
|
||||
ssSend << a1 << a2 << a3 << a4 << a5;
|
||||
EndMessage();
|
||||
} catch (...) {
|
||||
AbortMessage();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
|
||||
void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6)
|
||||
{
|
||||
try {
|
||||
BeginMessage(pszCommand);
|
||||
ssSend << a1 << a2 << a3 << a4 << a5 << a6;
|
||||
EndMessage();
|
||||
} catch (...) {
|
||||
AbortMessage();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
|
||||
void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7)
|
||||
{
|
||||
try {
|
||||
BeginMessage(pszCommand);
|
||||
ssSend << a1 << a2 << a3 << a4 << a5 << a6 << a7;
|
||||
EndMessage();
|
||||
} catch (...) {
|
||||
AbortMessage();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
|
||||
void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7, const T8& a8)
|
||||
{
|
||||
try {
|
||||
BeginMessage(pszCommand);
|
||||
ssSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8;
|
||||
EndMessage();
|
||||
} catch (...) {
|
||||
AbortMessage();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
|
||||
void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7, const T8& a8, const T9& a9)
|
||||
{
|
||||
try {
|
||||
BeginMessage(pszCommand);
|
||||
ssSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8 << a9;
|
||||
EndMessage();
|
||||
} catch (...) {
|
||||
AbortMessage();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10>
|
||||
void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7, const T8& a8, const T9& a9, const T10& a10)
|
||||
{
|
||||
try {
|
||||
BeginMessage(pszCommand);
|
||||
ssSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8 << a9 << a10;
|
||||
EndMessage();
|
||||
} catch (...) {
|
||||
AbortMessage();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11>
|
||||
void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7, const T8& a8, const T9& a9, const T10& a10, const T11& a11)
|
||||
{
|
||||
try {
|
||||
BeginMessage(pszCommand);
|
||||
ssSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8 << a9 << a10 << a11;
|
||||
EndMessage();
|
||||
} catch (...) {
|
||||
AbortMessage();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12>
|
||||
void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7, const T8& a8, const T9& a9, const T10& a10, const T11& a11, const T12& a12)
|
||||
{
|
||||
try {
|
||||
BeginMessage(pszCommand);
|
||||
ssSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8 << a9 << a10 << a11 << a12;
|
||||
EndMessage();
|
||||
} catch (...) {
|
||||
AbortMessage();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
bool HasFulfilledRequest(std::string strRequest)
|
||||
{
|
||||
for (std::string& type : vecRequestsFulfilled) {
|
||||
if (type == strRequest) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ClearFulfilledRequest(std::string strRequest)
|
||||
{
|
||||
std::vector<std::string>::iterator it = vecRequestsFulfilled.begin();
|
||||
while (it != vecRequestsFulfilled.end()) {
|
||||
if ((*it) == strRequest) {
|
||||
vecRequestsFulfilled.erase(it);
|
||||
return;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void FulfilledRequest(std::string strRequest)
|
||||
{
|
||||
if (HasFulfilledRequest(strRequest)) return;
|
||||
vecRequestsFulfilled.push_back(strRequest);
|
||||
}
|
||||
|
||||
bool IsSubscribed(unsigned int nChannel);
|
||||
void Subscribe(unsigned int nChannel, unsigned int nHops = 0);
|
||||
void CancelSubscribe(unsigned int nChannel);
|
||||
void CloseSocketDisconnect();
|
||||
bool DisconnectOldProtocol(int nVersionRequired, std::string strLastCommand = "");
|
||||
|
||||
// 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 entires (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();
|
||||
};
|
||||
|
||||
class CExplicitNetCleanup
|
||||
{
|
||||
public:
|
||||
static void callCleanup();
|
||||
};
|
||||
|
||||
class CTransaction;
|
||||
void RelayTransaction(const CTransaction& tx);
|
||||
void RelayTransaction(const CTransaction& tx, const CDataStream& ss);
|
||||
void RelayTransactionLockReq(const CTransaction& tx, bool relayToAll = false);
|
||||
void RelayInv(CInv& inv);
|
||||
|
||||
/** 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);
|
||||
};
|
||||
|
||||
/** 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);
|
||||
};
|
||||
|
||||
void DumpBanlist();
|
||||
|
||||
#endif // BITCOIN_NET_H
|
||||
Reference in New Issue
Block a user