|
|
@ -44,6 +44,7 @@ static map<CNetAddr, LocalServiceInfo> mapLocalHost; |
|
|
|
static bool vfReachable[NET_MAX] = {}; |
|
|
|
static bool vfReachable[NET_MAX] = {}; |
|
|
|
static bool vfLimited[NET_MAX] = {}; |
|
|
|
static bool vfLimited[NET_MAX] = {}; |
|
|
|
static CNode* pnodeLocalHost = NULL; |
|
|
|
static CNode* pnodeLocalHost = NULL; |
|
|
|
|
|
|
|
static CNode* pnodeSync = NULL; |
|
|
|
uint64 nLocalHostNonce = 0; |
|
|
|
uint64 nLocalHostNonce = 0; |
|
|
|
static std::vector<SOCKET> vhListenSocket; |
|
|
|
static std::vector<SOCKET> vhListenSocket; |
|
|
|
CAddrMan addrman; |
|
|
|
CAddrMan addrman; |
|
|
@ -515,12 +516,16 @@ void CNode::CloseSocketDisconnect() |
|
|
|
printf("disconnecting node %s\n", addrName.c_str()); |
|
|
|
printf("disconnecting node %s\n", addrName.c_str()); |
|
|
|
closesocket(hSocket); |
|
|
|
closesocket(hSocket); |
|
|
|
hSocket = INVALID_SOCKET; |
|
|
|
hSocket = INVALID_SOCKET; |
|
|
|
|
|
|
|
|
|
|
|
// in case this fails, we'll empty the recv buffer when the CNode is deleted
|
|
|
|
|
|
|
|
TRY_LOCK(cs_vRecvMsg, lockRecv); |
|
|
|
|
|
|
|
if (lockRecv) |
|
|
|
|
|
|
|
vRecvMsg.clear(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// in case this fails, we'll empty the recv buffer when the CNode is deleted
|
|
|
|
|
|
|
|
TRY_LOCK(cs_vRecvMsg, lockRecv); |
|
|
|
|
|
|
|
if (lockRecv) |
|
|
|
|
|
|
|
vRecvMsg.clear(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if this was the sync node, we'll need a new one
|
|
|
|
|
|
|
|
if (this == pnodeSync) |
|
|
|
|
|
|
|
pnodeSync = NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void CNode::Cleanup() |
|
|
|
void CNode::Cleanup() |
|
|
@ -607,6 +612,9 @@ void CNode::copyStats(CNodeStats &stats) |
|
|
|
X(fInbound); |
|
|
|
X(fInbound); |
|
|
|
X(nStartingHeight); |
|
|
|
X(nStartingHeight); |
|
|
|
X(nMisbehavior); |
|
|
|
X(nMisbehavior); |
|
|
|
|
|
|
|
X(nSendBytes); |
|
|
|
|
|
|
|
X(nRecvBytes); |
|
|
|
|
|
|
|
stats.fSyncNode = (this == pnodeSync); |
|
|
|
} |
|
|
|
} |
|
|
|
#undef X |
|
|
|
#undef X |
|
|
|
|
|
|
|
|
|
|
@ -701,6 +709,7 @@ void SocketSendData(CNode *pnode) |
|
|
|
int nBytes = send(pnode->hSocket, &data[pnode->nSendOffset], data.size() - pnode->nSendOffset, MSG_NOSIGNAL | MSG_DONTWAIT); |
|
|
|
int nBytes = send(pnode->hSocket, &data[pnode->nSendOffset], data.size() - pnode->nSendOffset, MSG_NOSIGNAL | MSG_DONTWAIT); |
|
|
|
if (nBytes > 0) { |
|
|
|
if (nBytes > 0) { |
|
|
|
pnode->nLastSend = GetTime(); |
|
|
|
pnode->nLastSend = GetTime(); |
|
|
|
|
|
|
|
pnode->nSendBytes += nBytes; |
|
|
|
pnode->nSendOffset += nBytes; |
|
|
|
pnode->nSendOffset += nBytes; |
|
|
|
if (pnode->nSendOffset == data.size()) { |
|
|
|
if (pnode->nSendOffset == data.size()) { |
|
|
|
pnode->nSendOffset = 0; |
|
|
|
pnode->nSendOffset = 0; |
|
|
@ -963,6 +972,7 @@ void ThreadSocketHandler() |
|
|
|
if (!pnode->ReceiveMsgBytes(pchBuf, nBytes)) |
|
|
|
if (!pnode->ReceiveMsgBytes(pchBuf, nBytes)) |
|
|
|
pnode->CloseSocketDisconnect(); |
|
|
|
pnode->CloseSocketDisconnect(); |
|
|
|
pnode->nLastRecv = GetTime(); |
|
|
|
pnode->nLastRecv = GetTime(); |
|
|
|
|
|
|
|
pnode->nRecvBytes += nBytes; |
|
|
|
} |
|
|
|
} |
|
|
|
else if (nBytes == 0) |
|
|
|
else if (nBytes == 0) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -1538,24 +1548,64 @@ bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOu |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// for now, use a very simple selection metric: the node from which we received
|
|
|
|
|
|
|
|
// most recently
|
|
|
|
|
|
|
|
double static NodeSyncScore(const CNode *pnode) { |
|
|
|
|
|
|
|
return -pnode->nLastRecv; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void static StartSync(const vector<CNode*> &vNodes) { |
|
|
|
|
|
|
|
CNode *pnodeNewSync = NULL; |
|
|
|
|
|
|
|
double dBestScore = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// fImporting and fReindex are accessed out of cs_main here, but only
|
|
|
|
|
|
|
|
// as an optimization - they are checked again in SendMessages.
|
|
|
|
|
|
|
|
if (fImporting || fReindex) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Iterate over all nodes
|
|
|
|
|
|
|
|
BOOST_FOREACH(CNode* pnode, vNodes) { |
|
|
|
|
|
|
|
// check preconditions for allowing a sync
|
|
|
|
|
|
|
|
if (!pnode->fClient && !pnode->fOneShot && |
|
|
|
|
|
|
|
!pnode->fDisconnect && pnode->fSuccessfullyConnected && |
|
|
|
|
|
|
|
(pnode->nStartingHeight > (nBestHeight - 144)) && |
|
|
|
|
|
|
|
(pnode->nVersion < NOBLKS_VERSION_START || pnode->nVersion >= NOBLKS_VERSION_END)) { |
|
|
|
|
|
|
|
// if ok, compare node's score with the best so far
|
|
|
|
|
|
|
|
double dScore = NodeSyncScore(pnode); |
|
|
|
|
|
|
|
if (pnodeNewSync == NULL || dScore > dBestScore) { |
|
|
|
|
|
|
|
pnodeNewSync = pnode; |
|
|
|
|
|
|
|
dBestScore = dScore; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// if a new sync candidate was found, start sync!
|
|
|
|
|
|
|
|
if (pnodeNewSync) { |
|
|
|
|
|
|
|
pnodeNewSync->fStartSync = true; |
|
|
|
|
|
|
|
pnodeSync = pnodeNewSync; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void ThreadMessageHandler() |
|
|
|
void ThreadMessageHandler() |
|
|
|
{ |
|
|
|
{ |
|
|
|
SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL); |
|
|
|
SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL); |
|
|
|
while (true) |
|
|
|
while (true) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
bool fHaveSyncNode = false; |
|
|
|
|
|
|
|
|
|
|
|
vector<CNode*> vNodesCopy; |
|
|
|
vector<CNode*> vNodesCopy; |
|
|
|
{ |
|
|
|
{ |
|
|
|
LOCK(cs_vNodes); |
|
|
|
LOCK(cs_vNodes); |
|
|
|
vNodesCopy = vNodes; |
|
|
|
vNodesCopy = vNodes; |
|
|
|
BOOST_FOREACH(CNode* pnode, vNodesCopy) |
|
|
|
BOOST_FOREACH(CNode* pnode, vNodesCopy) { |
|
|
|
pnode->AddRef(); |
|
|
|
pnode->AddRef(); |
|
|
|
|
|
|
|
if (pnode == pnodeSync) |
|
|
|
|
|
|
|
fHaveSyncNode = true; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!fHaveSyncNode) |
|
|
|
|
|
|
|
StartSync(vNodesCopy); |
|
|
|
|
|
|
|
|
|
|
|
// Poll the connected nodes for messages
|
|
|
|
// Poll the connected nodes for messages
|
|
|
|
CNode* pnodeTrickle = NULL; |
|
|
|
CNode* pnodeTrickle = NULL; |
|
|
|
if (!vNodesCopy.empty()) |
|
|
|
if (!vNodesCopy.empty()) |
|
|
|