aboutsummaryrefslogtreecommitdiff
path: root/src/net.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/net.cpp')
-rw-r--r--src/net.cpp162
1 files changed, 109 insertions, 53 deletions
diff --git a/src/net.cpp b/src/net.cpp
index 4ee1895a80..99457be0f5 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -3,6 +3,10 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#if defined(HAVE_CONFIG_H)
+#include "bitcoin-config.h"
+#endif
+
#include "chainparams.h"
#include "db.h"
#include "net.h"
@@ -15,6 +19,10 @@
#include <string.h>
#endif
+#ifndef WIN32
+#include <fcntl.h>
+#endif
+
#ifdef USE_UPNP
#include <miniupnpc/miniwget.h>
#include <miniupnpc/miniupnpc.h>
@@ -24,6 +32,9 @@
// Dump addresses to peers.dat every 15 minutes (900s)
#define DUMP_ADDRESSES_INTERVAL 900
+#if !defined(HAVE_MSG_NOSIGNAL)
+#define MSG_NOSIGNAL 0
+#endif
using namespace std;
using namespace boost;
@@ -162,14 +173,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: %d\n", nErr);
return false;
}
}
@@ -215,7 +226,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().c_str(), nScore);
{
LOCK(cs_mapLocalHost);
@@ -323,7 +334,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.c_str(), addr.ToString().c_str());
if (!addr.IsValid() || !addr.IsRoutable())
return false;
ipRet.SetIP(addr);
@@ -398,7 +409,7 @@ void ThreadGetMyExternalIP()
CNetAddr addrLocalHost;
if (GetMyExternalIP(addrLocalHost))
{
- printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
+ LogPrintf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
AddLocal(addrLocalHost, LOCAL_HTTP);
}
}
@@ -415,8 +426,10 @@ void AddressCurrentlyConnected(const CService& addr)
-
-
+uint64 CNode::nTotalBytesRecv = 0;
+uint64 CNode::nTotalBytesSent = 0;
+CCriticalSection CNode::cs_totalBytesRecv;
+CCriticalSection CNode::cs_totalBytesSent;
CNode* FindNode(const CNetAddr& ip)
{
@@ -462,7 +475,7 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
/// debug print
- printf("trying connection %s lastseen=%.1fhrs\n",
+ LogPrint("net", "trying connection %s lastseen=%.1fhrs\n",
pszDest ? pszDest : addrConnect.ToString().c_str(),
pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
@@ -472,17 +485,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().c_str());
// 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 %d\n", 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 %d\n", errno);
#endif
// Add node
@@ -508,7 +520,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.c_str());
closesocket(hSocket);
hSocket = INVALID_SOCKET;
}
@@ -530,12 +542,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());
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().c_str(), addrYou.ToString().c_str(), addr.ToString().c_str());
PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight, true);
}
@@ -572,7 +586,7 @@ bool CNode::Misbehaving(int howmuch)
{
if (addr.IsLocal())
{
- printf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch);
+ LogPrintf("Warning: Local node %s misbehaving (delta: %d)!\n", addrName.c_str(), howmuch);
return false;
}
@@ -580,7 +594,7 @@ bool CNode::Misbehaving(int 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);
+ LogPrintf("Misbehaving: %s (%d -> %d) DISCONNECTING\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
{
LOCK(cs_setBanned);
if (setBanned[addr] < banTime)
@@ -589,7 +603,7 @@ bool CNode::Misbehaving(int howmuch)
CloseSocketDisconnect();
return true;
} else
- printf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
+ LogPrintf("Misbehaving: %s (%d -> %d)\n", addr.ToString().c_str(), nMisbehavior-howmuch, nMisbehavior);
return false;
}
@@ -610,6 +624,21 @@ void CNode::copyStats(CNodeStats &stats)
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 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);
}
#undef X
@@ -706,6 +735,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 +750,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 %d\n", nErr);
pnode->CloseSocketDisconnect();
}
}
@@ -801,10 +831,9 @@ void ThreadSocketHandler()
}
}
}
- if (vNodes.size() != nPrevNodeCount)
- {
+ if(vNodes.size() != nPrevNodeCount) {
nPrevNodeCount = vNodes.size();
- uiInterface.NotifyNumConnectionsChanged(vNodes.size());
+ uiInterface.NotifyNumConnectionsChanged(nPrevNodeCount);
}
@@ -880,7 +909,7 @@ void ThreadSocketHandler()
if (have_fds)
{
int nErr = WSAGetLastError();
- printf("socket select error %d\n", nErr);
+ LogPrintf("socket select error %d\n", nErr);
for (unsigned int i = 0; i <= hSocketMax; i++)
FD_SET(i, &fdsetRecv);
}
@@ -908,7 +937,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,7 +950,7 @@ void ThreadSocketHandler()
{
int nErr = WSAGetLastError();
if (nErr != WSAEWOULDBLOCK)
- printf("socket error accept failed: %d\n", nErr);
+ LogPrintf("socket error accept failed: %d\n", nErr);
}
else if (nInbound >= nMaxConnections - MAX_OUTBOUND_CONNECTIONS)
{
@@ -933,12 +962,12 @@ void ThreadSocketHandler()
}
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().c_str());
closesocket(hSocket);
}
else
{
- printf("accepted connection %s\n", addr.ToString().c_str());
+ LogPrint("net", "accepted connection %s\n", addr.ToString().c_str());
CNode* pnode = new CNode(hSocket, addr, "", true);
pnode->AddRef();
{
@@ -983,12 +1012,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 +1028,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 %d\n", nErr);
pnode->CloseSocketDisconnect();
}
}
@@ -1027,17 +1057,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,16 +1119,16 @@ 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");
}
}
@@ -1117,10 +1147,10 @@ void ThreadMapPort()
#endif
if(r!=UPNPCOMMAND_SUCCESS)
- printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
+ LogPrintf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
port.c_str(), port.c_str(), 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 +1158,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 +1209,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 +1232,7 @@ void ThreadDNSAddressSeed()
}
}
- printf("%d addresses found from DNS seeds\n", found);
+ LogPrintf("%d addresses found from DNS seeds\n", found);
}
@@ -1223,7 +1253,7 @@ void DumpAddresses()
CAddrDB adb;
adb.Write(addrman);
- printf("Flushed %d addresses to peers.dat %"PRI64d"ms\n",
+ LogPrint("net", "Flushed %d addresses to peers.dat %"PRI64d"ms\n",
addrman.size(), GetTimeMillis() - nStart);
}
@@ -1281,7 +1311,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;
}
@@ -1457,6 +1487,8 @@ void static StartSync(const vector<CNode*> &vNodes) {
CNode *pnodeNewSync = NULL;
double dBestScore = 0;
+ int nBestHeight = g_signals.GetHeight().get_value_or(0);
+
// Iterate over all nodes
BOOST_FOREACH(CNode* pnode, vNodes) {
// check preconditions for allowing a sync
@@ -1557,7 +1589,7 @@ bool BindListenPort(const CService &addrBind, string& strError)
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());
+ LogPrintf("%s\n", strError.c_str());
return false;
}
@@ -1565,7 +1597,7 @@ bool BindListenPort(const CService &addrBind, string& strError)
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());
+ LogPrintf("%s\n", strError.c_str());
return false;
}
@@ -1589,7 +1621,7 @@ bool BindListenPort(const CService &addrBind, string& strError)
#endif
{
strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
- printf("%s\n", strError.c_str());
+ LogPrintf("%s\n", strError.c_str());
return false;
}
@@ -1620,16 +1652,16 @@ bool BindListenPort(const CService &addrBind, string& strError)
strError = strprintf(_("Unable to bind to %s on this computer. Bitcoin is probably already running."), addrBind.ToString().c_str());
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());
+ LogPrintf("%s\n", strError.c_str());
return false;
}
- printf("Bound to %s\n", addrBind.ToString().c_str());
+ LogPrintf("Bound to %s\n", addrBind.ToString().c_str());
// 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());
+ LogPrintf("%s\n", strError.c_str());
return false;
}
@@ -1676,7 +1708,7 @@ 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().c_str());
}
#ifdef USE_IPV6
else if (ifa->ifa_addr->sa_family == AF_INET6)
@@ -1684,7 +1716,7 @@ void static Discover()
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().c_str());
}
#endif
}
@@ -1715,7 +1747,7 @@ void StartNode(boost::thread_group& threadGroup)
//
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 +1774,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 +1800,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 %d\n", WSAGetLastError());
// clean up some globals (to help leak detection)
BOOST_FOREACH(CNode *pnode, vNodes)
@@ -1834,3 +1866,27 @@ void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataSt
pnode->PushInventory(inv);
}
}
+
+void CNode::RecordBytesRecv(uint64 bytes)
+{
+ LOCK(cs_totalBytesRecv);
+ nTotalBytesRecv += bytes;
+}
+
+void CNode::RecordBytesSent(uint64 bytes)
+{
+ LOCK(cs_totalBytesSent);
+ nTotalBytesSent += bytes;
+}
+
+uint64 CNode::GetTotalBytesRecv()
+{
+ LOCK(cs_totalBytesRecv);
+ return nTotalBytesRecv;
+}
+
+uint64 CNode::GetTotalBytesSent()
+{
+ LOCK(cs_totalBytesSent);
+ return nTotalBytesSent;
+}