|
|
@ -51,8 +51,8 @@ static const bool DEFAULT_UPNP = USE_UPNP; |
|
|
|
static const bool DEFAULT_UPNP = false; |
|
|
|
static const bool DEFAULT_UPNP = false; |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
inline unsigned int ReceiveFloodSize() { return 1000*GetArg("-maxreceivebuffer", 5*1000); } |
|
|
|
unsigned int ReceiveFloodSize(); |
|
|
|
inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 1*1000); } |
|
|
|
unsigned int SendBufferSize(); |
|
|
|
|
|
|
|
|
|
|
|
void AddOneShot(std::string strDest); |
|
|
|
void AddOneShot(std::string strDest); |
|
|
|
bool RecvLine(SOCKET hSocket, std::string& strLine); |
|
|
|
bool RecvLine(SOCKET hSocket, std::string& strLine); |
|
|
@ -300,70 +300,8 @@ public: |
|
|
|
// Whether a ping is requested.
|
|
|
|
// Whether a ping is requested.
|
|
|
|
bool fPingQueued; |
|
|
|
bool fPingQueued; |
|
|
|
|
|
|
|
|
|
|
|
CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn = "", bool fInboundIn=false) : ssSend(SER_NETWORK, INIT_PROTO_VERSION), setAddrKnown(5000) |
|
|
|
CNode(SOCKET hSocketIn, CAddress addrIn, std::string addrNameIn = "", bool fInboundIn=false); |
|
|
|
{ |
|
|
|
~CNode(); |
|
|
|
nServices = 0; |
|
|
|
|
|
|
|
hSocket = hSocketIn; |
|
|
|
|
|
|
|
nRecvVersion = INIT_PROTO_VERSION; |
|
|
|
|
|
|
|
nLastSend = 0; |
|
|
|
|
|
|
|
nLastRecv = 0; |
|
|
|
|
|
|
|
nSendBytes = 0; |
|
|
|
|
|
|
|
nRecvBytes = 0; |
|
|
|
|
|
|
|
nTimeConnected = GetTime(); |
|
|
|
|
|
|
|
addr = addrIn; |
|
|
|
|
|
|
|
addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn; |
|
|
|
|
|
|
|
nVersion = 0; |
|
|
|
|
|
|
|
strSubVer = ""; |
|
|
|
|
|
|
|
fWhitelisted = false; |
|
|
|
|
|
|
|
fOneShot = false; |
|
|
|
|
|
|
|
fClient = false; // set by version message
|
|
|
|
|
|
|
|
fInbound = fInboundIn; |
|
|
|
|
|
|
|
fNetworkNode = false; |
|
|
|
|
|
|
|
fSuccessfullyConnected = false; |
|
|
|
|
|
|
|
fDisconnect = false; |
|
|
|
|
|
|
|
nRefCount = 0; |
|
|
|
|
|
|
|
nSendSize = 0; |
|
|
|
|
|
|
|
nSendOffset = 0; |
|
|
|
|
|
|
|
hashContinue = 0; |
|
|
|
|
|
|
|
pindexLastGetBlocksBegin = 0; |
|
|
|
|
|
|
|
hashLastGetBlocksEnd = 0; |
|
|
|
|
|
|
|
nStartingHeight = -1; |
|
|
|
|
|
|
|
fStartSync = false; |
|
|
|
|
|
|
|
fGetAddr = false; |
|
|
|
|
|
|
|
fRelayTxes = false; |
|
|
|
|
|
|
|
setInventoryKnown.max_size(SendBufferSize() / 1000); |
|
|
|
|
|
|
|
pfilter = new CBloomFilter(); |
|
|
|
|
|
|
|
nPingNonceSent = 0; |
|
|
|
|
|
|
|
nPingUsecStart = 0; |
|
|
|
|
|
|
|
nPingUsecTime = 0; |
|
|
|
|
|
|
|
fPingQueued = false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
LOCK(cs_nLastNodeId); |
|
|
|
|
|
|
|
id = nLastNodeId++; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (fLogIPs) |
|
|
|
|
|
|
|
LogPrint("net", "Added connection to %s peer=%d\n", addrName, id); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
LogPrint("net", "Added connection peer=%d\n", id); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Be shy and don't send version until we hear
|
|
|
|
|
|
|
|
if (hSocket != INVALID_SOCKET && !fInbound) |
|
|
|
|
|
|
|
PushVersion(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GetNodeSignals().InitializeNode(GetId(), this); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
~CNode() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
CloseSocket(hSocket); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (pfilter) |
|
|
|
|
|
|
|
delete pfilter; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GetNodeSignals().FinalizeNode(GetId()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private: |
|
|
|
private: |
|
|
|
// Network usage totals
|
|
|
|
// Network usage totals
|
|
|
@ -452,96 +390,16 @@ public: |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void AskFor(const CInv& inv) |
|
|
|
void AskFor(const CInv& inv); |
|
|
|
{ |
|
|
|
|
|
|
|
// We're using mapAskFor as a priority queue,
|
|
|
|
|
|
|
|
// the key is the earliest time the request can be sent
|
|
|
|
|
|
|
|
int64_t nRequestTime; |
|
|
|
|
|
|
|
limitedmap<CInv, int64_t>::const_iterator it = mapAlreadyAskedFor.find(inv); |
|
|
|
|
|
|
|
if (it != mapAlreadyAskedFor.end()) |
|
|
|
|
|
|
|
nRequestTime = it->second; |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
nRequestTime = 0; |
|
|
|
|
|
|
|
LogPrint("net", "askfor %s %d (%s) peer=%d\n", inv.ToString(), nRequestTime, DateTimeStrFormat("%H:%M:%S", nRequestTime/1000000).c_str(), id); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Make sure not to reuse time indexes to keep things in the same order
|
|
|
|
|
|
|
|
int64_t nNow = GetTimeMicros() - 1000000; |
|
|
|
|
|
|
|
static int64_t nLastTime; |
|
|
|
|
|
|
|
++nLastTime; |
|
|
|
|
|
|
|
nNow = std::max(nNow, nLastTime); |
|
|
|
|
|
|
|
nLastTime = nNow; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Each retry is 2 minutes after the last
|
|
|
|
|
|
|
|
nRequestTime = std::max(nRequestTime + 2 * 60 * 1000000, nNow); |
|
|
|
|
|
|
|
if (it != mapAlreadyAskedFor.end()) |
|
|
|
|
|
|
|
mapAlreadyAskedFor.update(it, nRequestTime); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
mapAlreadyAskedFor.insert(std::make_pair(inv, nRequestTime)); |
|
|
|
|
|
|
|
mapAskFor.insert(std::make_pair(nRequestTime, inv)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: Document the postcondition of this function. Is cs_vSend locked?
|
|
|
|
// TODO: Document the postcondition of this function. Is cs_vSend locked?
|
|
|
|
void BeginMessage(const char* pszCommand) EXCLUSIVE_LOCK_FUNCTION(cs_vSend) |
|
|
|
void BeginMessage(const char* pszCommand) EXCLUSIVE_LOCK_FUNCTION(cs_vSend); |
|
|
|
{ |
|
|
|
|
|
|
|
ENTER_CRITICAL_SECTION(cs_vSend); |
|
|
|
|
|
|
|
assert(ssSend.size() == 0); |
|
|
|
|
|
|
|
ssSend << CMessageHeader(pszCommand, 0); |
|
|
|
|
|
|
|
LogPrint("net", "sending: %s ", pszCommand); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: Document the precondition of this function. Is cs_vSend locked?
|
|
|
|
// TODO: Document the precondition of this function. Is cs_vSend locked?
|
|
|
|
void AbortMessage() UNLOCK_FUNCTION(cs_vSend) |
|
|
|
void AbortMessage() UNLOCK_FUNCTION(cs_vSend); |
|
|
|
{ |
|
|
|
|
|
|
|
ssSend.clear(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LEAVE_CRITICAL_SECTION(cs_vSend); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LogPrint("net", "(aborted)\n"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: Document the precondition of this function. Is cs_vSend locked?
|
|
|
|
// TODO: Document the precondition of this function. Is cs_vSend locked?
|
|
|
|
void EndMessage() UNLOCK_FUNCTION(cs_vSend) |
|
|
|
void EndMessage() UNLOCK_FUNCTION(cs_vSend); |
|
|
|
{ |
|
|
|
|
|
|
|
// The -*messagestest options are intentionally not documented in the help message,
|
|
|
|
|
|
|
|
// since they are only used during development to debug the networking code and are
|
|
|
|
|
|
|
|
// not intended for end-users.
|
|
|
|
|
|
|
|
if (mapArgs.count("-dropmessagestest") && GetRand(GetArg("-dropmessagestest", 2)) == 0) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
LogPrint("net", "dropmessages DROPPING SEND MESSAGE\n"); |
|
|
|
|
|
|
|
AbortMessage(); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (mapArgs.count("-fuzzmessagestest")) |
|
|
|
|
|
|
|
Fuzz(GetArg("-fuzzmessagestest", 10)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (ssSend.size() == 0) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Set the size
|
|
|
|
|
|
|
|
unsigned int nSize = ssSend.size() - CMessageHeader::HEADER_SIZE; |
|
|
|
|
|
|
|
memcpy((char*)&ssSend[CMessageHeader::MESSAGE_SIZE_OFFSET], &nSize, sizeof(nSize)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Set the checksum
|
|
|
|
|
|
|
|
uint256 hash = Hash(ssSend.begin() + CMessageHeader::HEADER_SIZE, ssSend.end()); |
|
|
|
|
|
|
|
unsigned int nChecksum = 0; |
|
|
|
|
|
|
|
memcpy(&nChecksum, &hash, sizeof(nChecksum)); |
|
|
|
|
|
|
|
assert(ssSend.size () >= CMessageHeader::CHECKSUM_OFFSET + sizeof(nChecksum)); |
|
|
|
|
|
|
|
memcpy((char*)&ssSend[CMessageHeader::CHECKSUM_OFFSET], &nChecksum, sizeof(nChecksum)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LogPrint("net", "(%d bytes) peer=%d\n", nSize, id); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::deque<CSerializeData>::iterator it = vSendMsg.insert(vSendMsg.end(), CSerializeData()); |
|
|
|
|
|
|
|
ssSend.GetAndClear(*it); |
|
|
|
|
|
|
|
nSendSize += (*it).size(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// If write queue empty, attempt "optimistic write"
|
|
|
|
|
|
|
|
if (it == vSendMsg.begin()) |
|
|
|
|
|
|
|
SocketSendData(this); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LEAVE_CRITICAL_SECTION(cs_vSend); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PushVersion(); |
|
|
|
void PushVersion(); |
|
|
|
|
|
|
|
|
|
|
|