aboutsummaryrefslogtreecommitdiff
path: root/src/net.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/net.cpp')
-rw-r--r--src/net.cpp171
1 files changed, 89 insertions, 82 deletions
diff --git a/src/net.cpp b/src/net.cpp
index 479f77c46..934c45ca4 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -4,7 +4,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#if defined(HAVE_CONFIG_H)
-#include "bitcoin-config.h"
+#include "config/bitcoin-config.h"
#endif
#include "net.h"
@@ -36,6 +36,17 @@
#define MSG_NOSIGNAL 0
#endif
+// Fix for ancient MinGW versions, that don't have defined these in ws2tcpip.h.
+// Todo: Can be removed when our pull-tester is upgraded to a modern MinGW version.
+#ifdef WIN32
+#ifndef PROTECTION_LEVEL_UNRESTRICTED
+#define PROTECTION_LEVEL_UNRESTRICTED 10
+#endif
+#ifndef IPV6_PROTECTION_LEVEL
+#define IPV6_PROTECTION_LEVEL 23
+#endif
+#endif
+
using namespace std;
using namespace boost;
@@ -469,11 +480,10 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
}
}
-
/// debug print
LogPrint("net", "trying connection %s lastseen=%.1fhrs\n",
pszDest ? pszDest : addrConnect.ToString(),
- pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
+ pszDest ? 0.0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
// Connect
SOCKET hSocket;
@@ -505,10 +515,8 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
pnode->nTimeConnected = GetTime();
return pnode;
}
- else
- {
- return NULL;
- }
+
+ return NULL;
}
void CNode::CloseSocketDisconnect()
@@ -531,11 +539,6 @@ void CNode::CloseSocketDisconnect()
pnodeSync = NULL;
}
-void CNode::Cleanup()
-{
-}
-
-
void CNode::PushVersion()
{
int nBestHeight = g_signals.GetHeight().get_value_or(0);
@@ -682,7 +685,6 @@ int CNetMessage::readHeader(const char *pch, unsigned int nBytes)
// switch state to reading message data
in_data = true;
- vRecv.resize(hdr.nMessageSize);
return nCopy;
}
@@ -692,6 +694,11 @@ int CNetMessage::readData(const char *pch, unsigned int nBytes)
unsigned int nRemaining = hdr.nMessageSize - nDataPos;
unsigned int nCopy = std::min(nRemaining, nBytes);
+ if (vRecv.size() < nDataPos + nCopy) {
+ // Allocate up to 256 KiB ahead, but never more than the total message size.
+ vRecv.resize(std::min(hdr.nMessageSize, nDataPos + nCopy + 256 * 1024));
+ }
+
memcpy(&vRecv[nDataPos], pch, nCopy);
nDataPos += nCopy;
@@ -777,7 +784,6 @@ void ThreadSocketHandler()
// close socket and cleanup
pnode->CloseSocketDisconnect();
- pnode->Cleanup();
// hold in disconnected pool until all refs are released
if (pnode->fNetworkNode || pnode->fInbound)
@@ -821,7 +827,6 @@ void ThreadSocketHandler()
uiInterface.NotifyNumConnectionsChanged(nPrevNodeCount);
}
-
//
// Find which sockets have data to receive
//
@@ -843,6 +848,7 @@ void ThreadSocketHandler()
hSocketMax = max(hSocketMax, hListenSocket);
have_fds = true;
}
+
{
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
@@ -903,58 +909,59 @@ void ThreadSocketHandler()
MilliSleep(timeout.tv_usec/1000);
}
-
//
// Accept new connections
//
BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket)
- if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
{
- struct sockaddr_storage sockaddr;
- socklen_t len = sizeof(sockaddr);
- SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
- CAddress addr;
- int nInbound = 0;
-
- if (hSocket != INVALID_SOCKET)
- if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
- LogPrintf("Warning: Unknown socket family\n");
-
+ if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
{
- LOCK(cs_vNodes);
- BOOST_FOREACH(CNode* pnode, vNodes)
- if (pnode->fInbound)
- nInbound++;
- }
+ struct sockaddr_storage sockaddr;
+ socklen_t len = sizeof(sockaddr);
+ SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
+ CAddress addr;
+ int nInbound = 0;
+
+ if (hSocket != INVALID_SOCKET)
+ if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr))
+ LogPrintf("Warning: Unknown socket family\n");
- if (hSocket == INVALID_SOCKET)
- {
- int nErr = WSAGetLastError();
- if (nErr != WSAEWOULDBLOCK)
- LogPrintf("socket error accept failed: %s\n", NetworkErrorString(nErr));
- }
- else if (nInbound >= nMaxConnections - MAX_OUTBOUND_CONNECTIONS)
- {
- closesocket(hSocket);
- }
- else if (CNode::IsBanned(addr))
- {
- LogPrintf("connection from %s dropped (banned)\n", addr.ToString());
- closesocket(hSocket);
- }
- else
- {
- LogPrint("net", "accepted connection %s\n", addr.ToString());
- CNode* pnode = new CNode(hSocket, addr, "", true);
- pnode->AddRef();
{
LOCK(cs_vNodes);
- vNodes.push_back(pnode);
+ BOOST_FOREACH(CNode* pnode, vNodes)
+ if (pnode->fInbound)
+ nInbound++;
+ }
+
+ if (hSocket == INVALID_SOCKET)
+ {
+ int nErr = WSAGetLastError();
+ if (nErr != WSAEWOULDBLOCK)
+ LogPrintf("socket error accept failed: %s\n", NetworkErrorString(nErr));
+ }
+ else if (nInbound >= nMaxConnections - MAX_OUTBOUND_CONNECTIONS)
+ {
+ closesocket(hSocket);
+ }
+ else if (CNode::IsBanned(addr))
+ {
+ LogPrintf("connection from %s dropped (banned)\n", addr.ToString());
+ closesocket(hSocket);
+ }
+ else
+ {
+ LogPrint("net", "accepted connection %s\n", addr.ToString());
+ CNode* pnode = new CNode(hSocket, addr, "", true);
+ pnode->AddRef();
+
+ {
+ LOCK(cs_vNodes);
+ vNodes.push_back(pnode);
+ }
}
}
}
-
//
// Service each socket
//
@@ -1028,23 +1035,27 @@ void ThreadSocketHandler()
//
// Inactivity checking
//
- if (pnode->vSendMsg.empty())
- pnode->nLastSendEmpty = GetTime();
- if (GetTime() - pnode->nTimeConnected > 60)
+ int64_t nTime = GetTime();
+ if (nTime - pnode->nTimeConnected > 60)
{
if (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)
+ else if (nTime - pnode->nLastSend > TIMEOUT_INTERVAL)
+ {
+ LogPrintf("socket sending timeout: %is\n", nTime - pnode->nLastSend);
+ pnode->fDisconnect = true;
+ }
+ else if (nTime - pnode->nLastRecv > (pnode->nVersion > BIP0031_VERSION ? TIMEOUT_INTERVAL : 90*60))
{
- LogPrintf("socket not sending\n");
+ LogPrintf("socket receive timeout: %is\n", nTime - pnode->nLastRecv);
pnode->fDisconnect = true;
}
- else if (GetTime() - pnode->nLastRecv > 90*60)
+ else if (pnode->nPingNonceSent && pnode->nPingUsecStart + TIMEOUT_INTERVAL * 1000000 < GetTimeMicros())
{
- LogPrintf("socket inactivity timeout\n");
+ LogPrintf("ping timeout: %fs\n", 0.000001 * (GetTimeMicros() - pnode->nPingUsecStart));
pnode->fDisconnect = true;
}
}
@@ -1425,21 +1436,21 @@ void ThreadOpenAddedConnections()
}
// if successful, this moves the passed grant to the constructed node
-bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot)
+bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *pszDest, bool fOneShot)
{
//
// Initiate outbound network connection
//
boost::this_thread::interruption_point();
- if (!strDest)
+ if (!pszDest) {
if (IsLocal(addrConnect) ||
FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) ||
FindNode(addrConnect.ToStringIPPort().c_str()))
return false;
- if (strDest && FindNode(strDest))
+ } else if (FindNode(pszDest))
return false;
- CNode* pnode = ConnectNode(addrConnect, strDest);
+ CNode* pnode = ConnectNode(addrConnect, pszDest);
boost::this_thread::interruption_point();
if (!pnode)
@@ -1575,7 +1586,7 @@ bool BindListenPort(const CService &addrBind, string& strError)
socklen_t len = sizeof(sockaddr);
if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
{
- strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString());
+ strError = strprintf("Error: Bind address family for %s not supported", addrBind.ToString());
LogPrintf("%s\n", strError);
return false;
}
@@ -1588,18 +1599,16 @@ bool BindListenPort(const CService &addrBind, string& strError)
return false;
}
+#ifndef WIN32
#ifdef SO_NOSIGPIPE
// Different way of disabling SIGPIPE on BSD
setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
#endif
-
-#ifndef WIN32
// Allow binding if the port is still in TIME_WAIT state after
- // the program was closed and restarted. Not an issue on windows.
+ // the program was closed and restarted. Not an issue on windows!
setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
#endif
-
#ifdef WIN32
// Set to non-blocking, incoming connections will also inherit this
if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
@@ -1623,10 +1632,8 @@ bool BindListenPort(const CService &addrBind, string& strError)
#endif
#endif
#ifdef WIN32
- int nProtLevel = 10 /* PROTECTION_LEVEL_UNRESTRICTED */;
- int nParameterId = 23 /* IPV6_PROTECTION_LEVEl */;
- // this call is allowed to fail
- setsockopt(hListenSocket, IPPROTO_IPV6, nParameterId, (const char*)&nProtLevel, sizeof(int));
+ int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
+ setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
#endif
}
@@ -1769,9 +1776,8 @@ bool StopNode()
class CNetCleanup
{
public:
- CNetCleanup()
- {
- }
+ CNetCleanup() {}
+
~CNetCleanup()
{
// Close sockets
@@ -1790,6 +1796,7 @@ public:
delete pnode;
vNodes.clear();
vNodesDisconnected.clear();
+ vhListenSocket.clear();
delete semOutbound;
semOutbound = NULL;
delete pnodeLocalHost;
@@ -1809,17 +1816,17 @@ instance_of_cnetcleanup;
-void RelayTransaction(const CTransaction& tx, const uint256& hash)
+void RelayTransaction(const CTransaction& tx)
{
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(10000);
ss << tx;
- RelayTransaction(tx, hash, ss);
+ RelayTransaction(tx, ss);
}
-void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataStream& ss)
+void RelayTransaction(const CTransaction& tx, const CDataStream& ss)
{
- CInv inv(MSG_TX, hash);
+ CInv inv(MSG_TX, tx.GetHash());
{
LOCK(cs_mapRelay);
// Expire old relay messages
@@ -1841,7 +1848,7 @@ void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataSt
LOCK(pnode->cs_filter);
if (pnode->pfilter)
{
- if (pnode->pfilter->IsRelevantAndUpdate(tx, hash))
+ if (pnode->pfilter->IsRelevantAndUpdate(tx))
pnode->PushInventory(inv);
} else
pnode->PushInventory(inv);