This commit is contained in:
myriadcoin
2014-08-08 02:52:33 +02:00
parent 11736d62dd
commit 4739dcdb44
654 changed files with 190612 additions and 62862 deletions
+318 -141
View File
@@ -1,30 +1,41 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Copyright (c) 2009-2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "chainparams.h"
#include "db.h"
#if defined(HAVE_CONFIG_H)
#include "bitcoin-config.h"
#endif
#include "net.h"
#include "core.h"
#include "addrman.h"
#include "chainparams.h"
#include "core.h"
#include "ui_interface.h"
#include "script.h"
#ifdef WIN32
#include <string.h>
#else
#include <fcntl.h>
#endif
#ifdef USE_UPNP
#include <miniupnpc/miniwget.h>
#include <miniupnpc/miniupnpc.h>
#include <miniupnpc/miniwget.h>
#include <miniupnpc/upnpcommands.h>
#include <miniupnpc/upnperrors.h>
#endif
#include <boost/filesystem.hpp>
// Dump addresses to peers.dat every 15 minutes (900s)
#define DUMP_ADDRESSES_INTERVAL 900
#if !defined(HAVE_MSG_NOSIGNAL) && !defined(MSG_NOSIGNAL)
#define MSG_NOSIGNAL 0
#endif
using namespace std;
using namespace boost;
@@ -33,23 +44,18 @@ static const int MAX_OUTBOUND_CONNECTIONS = 8;
bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false);
struct LocalServiceInfo {
int nScore;
int nPort;
};
//
// Global state variables
//
bool fDiscover = true;
uint64 nLocalServices = NODE_NETWORK;
static CCriticalSection cs_mapLocalHost;
static map<CNetAddr, LocalServiceInfo> mapLocalHost;
uint64_t nLocalServices = NODE_NETWORK;
CCriticalSection cs_mapLocalHost;
map<CNetAddr, LocalServiceInfo> mapLocalHost;
static bool vfReachable[NET_MAX] = {};
static bool vfLimited[NET_MAX] = {};
static CNode* pnodeLocalHost = NULL;
static CNode* pnodeSync = NULL;
uint64 nLocalHostNonce = 0;
uint64_t nLocalHostNonce = 0;
static std::vector<SOCKET> vhListenSocket;
CAddrMan addrman;
int nMaxConnections = 125;
@@ -57,9 +63,9 @@ int nMaxConnections = 125;
vector<CNode*> vNodes;
CCriticalSection cs_vNodes;
map<CInv, CDataStream> mapRelay;
deque<pair<int64, CInv> > vRelayExpiration;
deque<pair<int64_t, CInv> > vRelayExpiration;
CCriticalSection cs_mapRelay;
limitedmap<CInv, int64> mapAlreadyAskedFor(MAX_INV_SZ);
limitedmap<CInv, int64_t> mapAlreadyAskedFor(MAX_INV_SZ);
static deque<string> vOneShots;
CCriticalSection cs_vOneShots;
@@ -70,6 +76,9 @@ CCriticalSection cs_setservAddNodeAddresses;
vector<std::string> vAddedNodes;
CCriticalSection cs_vAddedNodes;
NodeId nLastNodeId = 0;
CCriticalSection cs_nLastNodeId;
static CSemaphore *semOutbound = NULL;
// Signals for message handling
@@ -129,7 +138,7 @@ CAddress GetLocalAddress(const CNetAddr *paddrPeer)
bool RecvLine(SOCKET hSocket, string& strLine)
{
strLine = "";
loop
while (true)
{
char c;
int nBytes = recv(hSocket, &c, 1, 0);
@@ -162,14 +171,14 @@ bool RecvLine(SOCKET hSocket, string& strLine)
if (nBytes == 0)
{
// socket closed
printf("socket closed\n");
LogPrint("net", "socket closed\n");
return false;
}
else
{
// socket error
int nErr = WSAGetLastError();
printf("recv failed: %d\n", nErr);
LogPrint("net", "recv failed: %s\n", NetworkErrorString(nErr));
return false;
}
}
@@ -215,7 +224,7 @@ bool AddLocal(const CService& addr, int nScore)
if (IsLimited(addr))
return false;
printf("AddLocal(%s,%i)\n", addr.ToString().c_str(), nScore);
LogPrintf("AddLocal(%s,%i)\n", addr.ToString(), nScore);
{
LOCK(cs_mapLocalHost);
@@ -292,7 +301,7 @@ bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const cha
{
SOCKET hSocket;
if (!ConnectSocket(addrConnect, hSocket))
return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString().c_str());
return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString());
send(hSocket, pszGet, strlen(pszGet), MSG_NOSIGNAL);
@@ -301,7 +310,7 @@ bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const cha
{
if (strLine.empty()) // HTTP response is separated from headers by blank line
{
loop
while (true)
{
if (!RecvLine(hSocket, strLine))
{
@@ -323,7 +332,7 @@ bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const cha
while (strLine.size() > 0 && isspace(strLine[strLine.size()-1]))
strLine.resize(strLine.size()-1);
CService addr(strLine,0,true);
printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str());
LogPrintf("GetMyExternalIP() received [%s] %s\n", strLine, addr.ToString());
if (!addr.IsValid() || !addr.IsRoutable())
return false;
ipRet.SetIP(addr);
@@ -398,7 +407,7 @@ void ThreadGetMyExternalIP()
CNetAddr addrLocalHost;
if (GetMyExternalIP(addrLocalHost))
{
printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
LogPrintf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP());
AddLocal(addrLocalHost, LOCAL_HTTP);
}
}
@@ -415,8 +424,10 @@ void AddressCurrentlyConnected(const CService& addr)
uint64_t CNode::nTotalBytesRecv = 0;
uint64_t CNode::nTotalBytesSent = 0;
CCriticalSection CNode::cs_totalBytesRecv;
CCriticalSection CNode::cs_totalBytesSent;
CNode* FindNode(const CNetAddr& ip)
{
@@ -462,8 +473,8 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
/// debug print
printf("trying connection %s lastseen=%.1fhrs\n",
pszDest ? pszDest : addrConnect.ToString().c_str(),
LogPrint("net", "trying connection %s lastseen=%.1fhrs\n",
pszDest ? pszDest : addrConnect.ToString(),
pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
// Connect
@@ -472,17 +483,16 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
{
addrman.Attempt(addrConnect);
/// debug print
printf("connected %s\n", pszDest ? pszDest : addrConnect.ToString().c_str());
LogPrint("net", "connected %s\n", pszDest ? pszDest : addrConnect.ToString());
// Set to non-blocking
#ifdef WIN32
u_long nOne = 1;
if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
printf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %d\n", WSAGetLastError());
LogPrintf("ConnectSocket() : ioctlsocket non-blocking setting failed, error %s\n", NetworkErrorString(WSAGetLastError()));
#else
if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
printf("ConnectSocket() : fcntl non-blocking setting failed, error %d\n", errno);
LogPrintf("ConnectSocket() : fcntl non-blocking setting failed, error %s\n", NetworkErrorString(errno));
#endif
// Add node
@@ -508,7 +518,7 @@ void CNode::CloseSocketDisconnect()
fDisconnect = true;
if (hSocket != INVALID_SOCKET)
{
printf("disconnecting node %s\n", addrName.c_str());
LogPrint("net", "disconnecting node %s\n", addrName);
closesocket(hSocket);
hSocket = INVALID_SOCKET;
}
@@ -530,12 +540,14 @@ void CNode::Cleanup()
void CNode::PushVersion()
{
int nBestHeight = g_signals.GetHeight().get_value_or(0);
/// when NTP implemented, change to just nTime = GetAdjustedTime()
int64 nTime = (fInbound ? GetAdjustedTime() : GetTime());
int64_t nTime = (fInbound ? GetAdjustedTime() : GetTime());
CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0)));
CAddress addrMe = GetLocalAddress(&addr);
RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
printf("send version message: version %d, blocks=%d, us=%s, them=%s, peer=%s\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString().c_str(), addrYou.ToString().c_str(), addr.ToString().c_str());
LogPrint("net", "send version message: version %d, blocks=%d, us=%s, them=%s, peer=%s\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString(), addrYou.ToString(), addr.ToString());
PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight, true);
}
@@ -544,7 +556,7 @@ void CNode::PushVersion()
std::map<CNetAddr, int64> CNode::setBanned;
std::map<CNetAddr, int64_t> CNode::setBanned;
CCriticalSection CNode::cs_setBanned;
void CNode::ClearBanned()
@@ -557,10 +569,10 @@ bool CNode::IsBanned(CNetAddr ip)
bool fResult = false;
{
LOCK(cs_setBanned);
std::map<CNetAddr, int64>::iterator i = setBanned.find(ip);
std::map<CNetAddr, int64_t>::iterator i = setBanned.find(ip);
if (i != setBanned.end())
{
int64 t = (*i).second;
int64_t t = (*i).second;
if (GetTime() < t)
fResult = true;
}
@@ -568,48 +580,51 @@ bool CNode::IsBanned(CNetAddr ip)
return fResult;
}
bool CNode::Misbehaving(int howmuch)
{
if (addr.IsLocal())
bool CNode::Ban(const CNetAddr &addr) {
int64_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
{
printf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch);
return false;
LOCK(cs_setBanned);
if (setBanned[addr] < banTime)
setBanned[addr] = banTime;
}
nMisbehavior += howmuch;
if (nMisbehavior >= GetArg("-banscore", 100))
{
int64 banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
printf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
{
LOCK(cs_setBanned);
if (setBanned[addr] < banTime)
setBanned[addr] = banTime;
}
CloseSocketDisconnect();
return true;
} else
printf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
return false;
return true;
}
#undef X
#define X(name) stats.name = name
void CNode::copyStats(CNodeStats &stats)
{
stats.nodeid = this->GetId();
X(nServices);
X(nLastSend);
X(nLastRecv);
X(nTimeConnected);
X(addrName);
X(nVersion);
X(strSubVer);
X(cleanSubVer);
X(fInbound);
X(nStartingHeight);
X(nMisbehavior);
X(nSendBytes);
X(nRecvBytes);
stats.fSyncNode = (this == pnodeSync);
// It is common for nodes with good ping times to suddenly become lagged,
// due to a new block arriving or other large transfer.
// Merely reporting pingtime might fool the caller into thinking the node was still responsive,
// since pingtime does not update until the ping is complete, which might take a while.
// So, if a ping is taking an unusually long time in flight,
// the caller can immediately detect that this is happening.
int64_t nPingUsecWait = 0;
if ((0 != nPingNonceSent) && (0 != nPingUsecStart)) {
nPingUsecWait = GetTimeMicros() - nPingUsecStart;
}
// Raw ping time is in microseconds, but show it to user as whole seconds (Bitcoin users should be well used to small numbers with many decimal places by now :)
stats.dPingTime = (((double)nPingUsecTime) / 1e6);
stats.dPingWait = (((double)nPingUsecWait) / 1e6);
// Leave string empty if addrLocal invalid (not filled in yet)
stats.addrLocal = addrLocal.IsValid() ? addrLocal.ToString() : "";
}
#undef X
@@ -706,6 +721,7 @@ void SocketSendData(CNode *pnode)
pnode->nLastSend = GetTime();
pnode->nSendBytes += nBytes;
pnode->nSendOffset += nBytes;
pnode->RecordBytesSent(nBytes);
if (pnode->nSendOffset == data.size()) {
pnode->nSendOffset = 0;
pnode->nSendSize -= data.size();
@@ -720,7 +736,7 @@ void SocketSendData(CNode *pnode)
int nErr = WSAGetLastError();
if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
{
printf("socket send error %d\n", nErr);
LogPrintf("socket send error %s\n", NetworkErrorString(nErr));
pnode->CloseSocketDisconnect();
}
}
@@ -741,7 +757,7 @@ static list<CNode*> vNodesDisconnected;
void ThreadSocketHandler()
{
unsigned int nPrevNodeCount = 0;
loop
while (true)
{
//
// Disconnect nodes
@@ -771,7 +787,8 @@ void ThreadSocketHandler()
vNodesDisconnected.push_back(pnode);
}
}
}
{
// Delete disconnected nodes
list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
@@ -801,10 +818,9 @@ void ThreadSocketHandler()
}
}
}
if (vNodes.size() != nPrevNodeCount)
{
if(vNodes.size() != nPrevNodeCount) {
nPrevNodeCount = vNodes.size();
uiInterface.NotifyNumConnectionsChanged(vNodes.size());
uiInterface.NotifyNumConnectionsChanged(nPrevNodeCount);
}
@@ -880,7 +896,7 @@ void ThreadSocketHandler()
if (have_fds)
{
int nErr = WSAGetLastError();
printf("socket select error %d\n", nErr);
LogPrintf("socket select error %s\n", NetworkErrorString(nErr));
for (unsigned int i = 0; i <= hSocketMax; i++)
FD_SET(i, &fdsetRecv);
}
@@ -896,11 +912,7 @@ void ThreadSocketHandler()
BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
{
#ifdef USE_IPV6
struct sockaddr_storage sockaddr;
#else
struct sockaddr sockaddr;
#endif
socklen_t len = sizeof(sockaddr);
SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
CAddress addr;
@@ -908,7 +920,7 @@ void ThreadSocketHandler()
if (hSocket != INVALID_SOCKET)
if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
printf("Warning: Unknown socket family\n");
LogPrintf("Warning: Unknown socket family\n");
{
LOCK(cs_vNodes);
@@ -921,24 +933,20 @@ void ThreadSocketHandler()
{
int nErr = WSAGetLastError();
if (nErr != WSAEWOULDBLOCK)
printf("socket error accept failed: %d\n", nErr);
LogPrintf("socket error accept failed: %s\n", NetworkErrorString(nErr));
}
else if (nInbound >= nMaxConnections - MAX_OUTBOUND_CONNECTIONS)
{
{
LOCK(cs_setservAddNodeAddresses);
if (!setservAddNodeAddresses.count(addr))
closesocket(hSocket);
}
closesocket(hSocket);
}
else if (CNode::IsBanned(addr))
{
printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
LogPrintf("connection from %s dropped (banned)\n", addr.ToString());
closesocket(hSocket);
}
else
{
printf("accepted connection %s\n", addr.ToString().c_str());
LogPrint("net", "accepted connection %s\n", addr.ToString());
CNode* pnode = new CNode(hSocket, addr, "", true);
pnode->AddRef();
{
@@ -983,12 +991,13 @@ void ThreadSocketHandler()
pnode->CloseSocketDisconnect();
pnode->nLastRecv = GetTime();
pnode->nRecvBytes += nBytes;
pnode->RecordBytesRecv(nBytes);
}
else if (nBytes == 0)
{
// socket closed gracefully
if (!pnode->fDisconnect)
printf("socket closed\n");
LogPrint("net", "socket closed\n");
pnode->CloseSocketDisconnect();
}
else if (nBytes < 0)
@@ -998,7 +1007,7 @@ void ThreadSocketHandler()
if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
{
if (!pnode->fDisconnect)
printf("socket recv error %d\n", nErr);
LogPrintf("socket recv error %s\n", NetworkErrorString(nErr));
pnode->CloseSocketDisconnect();
}
}
@@ -1027,17 +1036,17 @@ void ThreadSocketHandler()
{
if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
{
printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
LogPrint("net", "socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
pnode->fDisconnect = true;
}
else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
{
printf("socket not sending\n");
LogPrintf("socket not sending\n");
pnode->fDisconnect = true;
}
else if (GetTime() - pnode->nLastRecv > 90*60)
{
printf("socket inactivity timeout\n");
LogPrintf("socket inactivity timeout\n");
pnode->fDisconnect = true;
}
}
@@ -1089,23 +1098,23 @@ void ThreadMapPort()
char externalIPAddress[40];
r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
if(r != UPNPCOMMAND_SUCCESS)
printf("UPnP: GetExternalIPAddress() returned %d\n", r);
LogPrintf("UPnP: GetExternalIPAddress() returned %d\n", r);
else
{
if(externalIPAddress[0])
{
printf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
LogPrintf("UPnP: ExternalIPAddress = %s\n", externalIPAddress);
AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP);
}
else
printf("UPnP: GetExternalIPAddress failed.\n");
LogPrintf("UPnP: GetExternalIPAddress failed.\n");
}
}
string strDesc = "Myriadcoin " + FormatFullVersion();
try {
loop {
while (true) {
#ifndef UPNPDISCOVER_SUCCESS
/* miniupnpc 1.5 */
r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
@@ -1117,10 +1126,10 @@ void ThreadMapPort()
#endif
if(r!=UPNPCOMMAND_SUCCESS)
printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
LogPrintf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
port, port, lanaddr, r, strupnperror(r));
else
printf("UPnP Port Mapping successful.\n");;
LogPrintf("UPnP Port Mapping successful.\n");;
MilliSleep(20*60*1000); // Refresh every 20 minutes
}
@@ -1128,13 +1137,13 @@ void ThreadMapPort()
catch (boost::thread_interrupted)
{
r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
printf("UPNP_DeletePortMapping() returned : %d\n", r);
LogPrintf("UPNP_DeletePortMapping() returned : %d\n", r);
freeUPNPDevlist(devlist); devlist = 0;
FreeUPNPUrls(&urls);
throw;
}
} else {
printf("No valid UPnP IGDs found\n");
LogPrintf("No valid UPnP IGDs found\n");
freeUPNPDevlist(devlist); devlist = 0;
if (r != 0)
FreeUPNPUrls(&urls);
@@ -1179,7 +1188,7 @@ void ThreadDNSAddressSeed()
const vector<CDNSSeedData> &vSeeds = Params().DNSSeeds();
int found = 0;
printf("Loading addresses from DNS seeds (could take a while)\n");
LogPrintf("Loading addresses from DNS seeds (could take a while)\n");
BOOST_FOREACH(const CDNSSeedData &seed, vSeeds) {
if (HaveNameProxy()) {
@@ -1202,7 +1211,7 @@ void ThreadDNSAddressSeed()
}
}
printf("%d addresses found from DNS seeds\n", found);
LogPrintf("%d addresses found from DNS seeds\n", found);
}
@@ -1218,12 +1227,12 @@ void ThreadDNSAddressSeed()
void DumpAddresses()
{
int64 nStart = GetTimeMillis();
int64_t nStart = GetTimeMillis();
CAddrDB adb;
adb.Write(addrman);
printf("Flushed %d addresses to peers.dat %"PRI64d"ms\n",
LogPrint("net", "Flushed %d addresses to peers.dat %dms\n",
addrman.size(), GetTimeMillis() - nStart);
}
@@ -1250,7 +1259,7 @@ void ThreadOpenConnections()
// Connect to specific addresses
if (mapArgs.count("-connect") && mapMultiArgs["-connect"].size() > 0)
{
for (int64 nLoop = 0;; nLoop++)
for (int64_t nLoop = 0;; nLoop++)
{
ProcessOneShot();
BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
@@ -1267,8 +1276,8 @@ void ThreadOpenConnections()
}
// Initiate network connections
int64 nStart = GetTime();
loop
int64_t nStart = GetTime();
while (true)
{
ProcessOneShot();
@@ -1281,7 +1290,7 @@ void ThreadOpenConnections()
if (addrman.size() == 0 && (GetTime() - nStart > 60)) {
static bool done = false;
if (!done) {
printf("Adding fixed seed nodes as DNS doesn't seem to be available.\n");
LogPrintf("Adding fixed seed nodes as DNS doesn't seem to be available.\n");
addrman.Add(Params().FixedSeeds(), CNetAddr("127.0.0.1"));
done = true;
}
@@ -1306,10 +1315,10 @@ void ThreadOpenConnections()
}
}
int64 nANow = GetAdjustedTime();
int64_t nANow = GetAdjustedTime();
int nTries = 0;
loop
while (true)
{
// use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections)
CAddress addr = addrman.Select(10 + min(nOutbound,8)*10);
@@ -1449,13 +1458,15 @@ 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;
static int64_t NodeSyncScore(const CNode *pnode) {
return pnode->nLastRecv;
}
void static StartSync(const vector<CNode*> &vNodes) {
CNode *pnodeNewSync = NULL;
double dBestScore = 0;
int64_t nBestScore = 0;
int nBestHeight = g_signals.GetHeight().get_value_or(0);
// Iterate over all nodes
BOOST_FOREACH(CNode* pnode, vNodes) {
@@ -1465,10 +1476,10 @@ void static StartSync(const vector<CNode*> &vNodes) {
(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) {
int64_t nScore = NodeSyncScore(pnode);
if (pnodeNewSync == NULL || nScore > nBestScore) {
pnodeNewSync = pnode;
dBestScore = dScore;
nBestScore = nScore;
}
}
}
@@ -1504,6 +1515,9 @@ void ThreadMessageHandler()
CNode* pnodeTrickle = NULL;
if (!vNodesCopy.empty())
pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
bool fSleep = true;
BOOST_FOREACH(CNode* pnode, vNodesCopy)
{
if (pnode->fDisconnect)
@@ -1513,8 +1527,18 @@ void ThreadMessageHandler()
{
TRY_LOCK(pnode->cs_vRecvMsg, lockRecv);
if (lockRecv)
{
if (!g_signals.ProcessMessages(pnode))
pnode->CloseSocketDisconnect();
if (pnode->nSendSize < SendBufferSize())
{
if (!pnode->vRecvGetData.empty() || (!pnode->vRecvMsg.empty() && pnode->vRecvMsg[0].complete()))
{
fSleep = false;
}
}
}
}
boost::this_thread::interruption_point();
@@ -1533,7 +1557,8 @@ void ThreadMessageHandler()
pnode->Release();
}
MilliSleep(20);
if (fSleep)
MilliSleep(100);
}
}
@@ -1548,24 +1573,20 @@ bool BindListenPort(const CService &addrBind, string& strError)
int nOne = 1;
// Create socket for listening for incoming connections
#ifdef USE_IPV6
struct sockaddr_storage sockaddr;
#else
struct sockaddr sockaddr;
#endif
socklen_t len = sizeof(sockaddr);
if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
{
strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str());
printf("%s\n", strError.c_str());
strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString());
LogPrintf("%s\n", strError);
return false;
}
SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP);
if (hListenSocket == INVALID_SOCKET)
{
strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
printf("%s\n", strError.c_str());
strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %s)", NetworkErrorString(WSAGetLastError()));
LogPrintf("%s\n", strError);
return false;
}
@@ -1588,12 +1609,11 @@ bool BindListenPort(const CService &addrBind, string& strError)
if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
#endif
{
strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
printf("%s\n", strError.c_str());
strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %s)", NetworkErrorString(WSAGetLastError()));
LogPrintf("%s\n", strError);
return false;
}
#ifdef USE_IPV6
// some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
// and enable it by default or not. Try to enable it, if possible.
if (addrBind.IsIPv6()) {
@@ -1611,25 +1631,24 @@ bool BindListenPort(const CService &addrBind, string& strError)
setsockopt(hListenSocket, IPPROTO_IPV6, nParameterId, (const char*)&nProtLevel, sizeof(int));
#endif
}
#endif
if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
{
int nErr = WSAGetLastError();
if (nErr == WSAEADDRINUSE)
strError = strprintf(_("Unable to bind to %s on this computer. Myriadcoin is probably already running."), addrBind.ToString().c_str());
strError = strprintf(_("Unable to bind to %s on this computer. Myriadcoin Core is probably already running."), addrBind.ToString());
else
strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr));
printf("%s\n", strError.c_str());
strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %s)"), addrBind.ToString(), NetworkErrorString(nErr));
LogPrintf("%s\n", strError);
return false;
}
printf("Bound to %s\n", addrBind.ToString().c_str());
LogPrintf("Bound to %s\n", addrBind.ToString());
// Listen for incoming connections
if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
{
strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
printf("%s\n", strError.c_str());
strError = strprintf(_("Error: Listening for incoming connections failed (listen returned error %s)"), NetworkErrorString(WSAGetLastError()));
LogPrintf("%s\n", strError);
return false;
}
@@ -1641,7 +1660,7 @@ bool BindListenPort(const CService &addrBind, string& strError)
return true;
}
void static Discover()
void static Discover(boost::thread_group& threadGroup)
{
if (!fDiscover)
return;
@@ -1676,17 +1695,15 @@ void static Discover()
struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
CNetAddr addr(s4->sin_addr);
if (AddLocal(addr, LOCAL_IF))
printf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
LogPrintf("IPv4 %s: %s\n", ifa->ifa_name, addr.ToString());
}
#ifdef USE_IPV6
else if (ifa->ifa_addr->sa_family == AF_INET6)
{
struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
CNetAddr addr(s6->sin6_addr);
if (AddLocal(addr, LOCAL_IF))
printf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
LogPrintf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString());
}
#endif
}
freeifaddrs(myaddrs);
}
@@ -1694,7 +1711,7 @@ void static Discover()
// Don't use external IPv4 discovery, when -onlynet="IPv6"
if (!IsLimited(NET_IPV4))
boost::thread(boost::bind(&TraceThread<void (*)()>, "ext-ip", &ThreadGetMyExternalIP));
threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "ext-ip", &ThreadGetMyExternalIP));
}
void StartNode(boost::thread_group& threadGroup)
@@ -1708,14 +1725,14 @@ void StartNode(boost::thread_group& threadGroup)
if (pnodeLocalHost == NULL)
pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices));
Discover();
Discover(threadGroup);
//
// Start threads
//
if (!GetBoolArg("-dnsseed", true))
printf("DNS seeding disabled\n");
LogPrintf("DNS seeding disabled\n");
else
threadGroup.create_thread(boost::bind(&TraceThread<void (*)()>, "dnsseed", &ThreadDNSAddressSeed));
@@ -1742,7 +1759,7 @@ void StartNode(boost::thread_group& threadGroup)
bool StopNode()
{
printf("StopNode()\n");
LogPrintf("StopNode()\n");
MapPort(false);
if (semOutbound)
for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++)
@@ -1768,7 +1785,7 @@ public:
BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
if (hListenSocket != INVALID_SOCKET)
if (closesocket(hListenSocket) == SOCKET_ERROR)
printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
LogPrintf("closesocket(hListenSocket) failed with error %s\n", NetworkErrorString(WSAGetLastError()));
// clean up some globals (to help leak detection)
BOOST_FOREACH(CNode *pnode, vNodes)
@@ -1834,3 +1851,163 @@ void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataSt
pnode->PushInventory(inv);
}
}
void CNode::RecordBytesRecv(uint64_t bytes)
{
LOCK(cs_totalBytesRecv);
nTotalBytesRecv += bytes;
}
void CNode::RecordBytesSent(uint64_t bytes)
{
LOCK(cs_totalBytesSent);
nTotalBytesSent += bytes;
}
uint64_t CNode::GetTotalBytesRecv()
{
LOCK(cs_totalBytesRecv);
return nTotalBytesRecv;
}
uint64_t CNode::GetTotalBytesSent()
{
LOCK(cs_totalBytesSent);
return nTotalBytesSent;
}
void CNode::Fuzz(int nChance)
{
if (!fSuccessfullyConnected) return; // Don't fuzz initial handshake
if (GetRand(nChance) != 0) return; // Fuzz 1 of every nChance messages
switch (GetRand(3))
{
case 0:
// xor a random byte with a random value:
if (!ssSend.empty()) {
CDataStream::size_type pos = GetRand(ssSend.size());
ssSend[pos] ^= (unsigned char)(GetRand(256));
}
break;
case 1:
// delete a random byte:
if (!ssSend.empty()) {
CDataStream::size_type pos = GetRand(ssSend.size());
ssSend.erase(ssSend.begin()+pos);
}
break;
case 2:
// insert a random byte at a random position
{
CDataStream::size_type pos = GetRand(ssSend.size());
char ch = (char)GetRand(256);
ssSend.insert(ssSend.begin()+pos, ch);
}
break;
}
// Chance of more than one change half the time:
// (more changes exponentially less likely):
Fuzz(2);
}
//
// CAddrDB
//
CAddrDB::CAddrDB()
{
pathAddr = GetDataDir() / "peers.dat";
}
bool CAddrDB::Write(const CAddrMan& addr)
{
// Generate random temporary filename
unsigned short randv = 0;
RAND_bytes((unsigned char *)&randv, sizeof(randv));
std::string tmpfn = strprintf("peers.dat.%04x", randv);
// serialize addresses, checksum data up to that point, then append csum
CDataStream ssPeers(SER_DISK, CLIENT_VERSION);
ssPeers << FLATDATA(Params().MessageStart());
ssPeers << addr;
uint256 hash = Hash(ssPeers.begin(), ssPeers.end());
ssPeers << hash;
// open temp output file, and associate with CAutoFile
boost::filesystem::path pathTmp = GetDataDir() / tmpfn;
FILE *file = fopen(pathTmp.string().c_str(), "wb");
CAutoFile fileout = CAutoFile(file, SER_DISK, CLIENT_VERSION);
if (!fileout)
return error("%s : Failed to open file %s", __func__, pathTmp.string());
// Write and commit header, data
try {
fileout << ssPeers;
}
catch (std::exception &e) {
return error("%s : Serialize or I/O error - %s", __func__, e.what());
}
FileCommit(fileout);
fileout.fclose();
// replace existing peers.dat, if any, with new peers.dat.XXXX
if (!RenameOver(pathTmp, pathAddr))
return error("%s : Rename-into-place failed", __func__);
return true;
}
bool CAddrDB::Read(CAddrMan& addr)
{
// open input file, and associate with CAutoFile
FILE *file = fopen(pathAddr.string().c_str(), "rb");
CAutoFile filein = CAutoFile(file, SER_DISK, CLIENT_VERSION);
if (!filein)
return error("%s : Failed to open file %s", __func__, pathAddr.string());
// use file size to size memory buffer
int fileSize = boost::filesystem::file_size(pathAddr);
int dataSize = fileSize - sizeof(uint256);
// Don't try to resize to a negative number if file is small
if (dataSize < 0)
dataSize = 0;
vector<unsigned char> vchData;
vchData.resize(dataSize);
uint256 hashIn;
// read data and checksum from file
try {
filein.read((char *)&vchData[0], dataSize);
filein >> hashIn;
}
catch (std::exception &e) {
return error("%s : Deserialize or I/O error - %s", __func__, e.what());
}
filein.fclose();
CDataStream ssPeers(vchData, SER_DISK, CLIENT_VERSION);
// verify stored checksum matches input data
uint256 hashTmp = Hash(ssPeers.begin(), ssPeers.end());
if (hashIn != hashTmp)
return error("%s : Checksum mismatch, data corrupted", __func__);
unsigned char pchMsgTmp[4];
try {
// de-serialize file header (network specific magic number) and ..
ssPeers >> FLATDATA(pchMsgTmp);
// ... verify the network matches ours
if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
return error("%s : Invalid network magic number", __func__);
// de-serialize address data into one CAddrMan object
ssPeers >> addr;
}
catch (std::exception &e) {
return error("%s : Deserialize or I/O error - %s", __func__, e.what());
}
return true;
}