aboutsummaryrefslogtreecommitdiff
path: root/src/net.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/net.cpp')
-rw-r--r--src/net.cpp187
1 files changed, 137 insertions, 50 deletions
diff --git a/src/net.cpp b/src/net.cpp
index c547cf333..359e62929 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2013 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.
@@ -12,7 +12,6 @@
#include "addrman.h"
#include "chainparams.h"
#include "core.h"
-#include "db.h"
#include "ui_interface.h"
#ifdef WIN32
@@ -80,6 +79,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
@@ -225,7 +227,7 @@ bool AddLocal(const CService& addr, int nScore)
if (IsLimited(addr))
return false;
- LogPrintf("AddLocal(%s,%i)\n", addr.ToString().c_str(), nScore);
+ LogPrintf("AddLocal(%s,%i)\n", addr.ToString(), nScore);
{
LOCK(cs_mapLocalHost);
@@ -302,7 +304,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);
@@ -333,7 +335,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);
- LogPrintf("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);
@@ -408,7 +410,7 @@ void ThreadGetMyExternalIP()
CNetAddr addrLocalHost;
if (GetMyExternalIP(addrLocalHost))
{
- LogPrintf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
+ LogPrintf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP());
AddLocal(addrLocalHost, LOCAL_HTTP);
}
}
@@ -475,7 +477,7 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
/// debug print
LogPrint("net", "trying connection %s lastseen=%.1fhrs\n",
- pszDest ? pszDest : addrConnect.ToString().c_str(),
+ pszDest ? pszDest : addrConnect.ToString(),
pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
// Connect
@@ -484,7 +486,7 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
{
addrman.Attempt(addrConnect);
- LogPrint("net", "connected %s\n", pszDest ? pszDest : addrConnect.ToString().c_str());
+ LogPrint("net", "connected %s\n", pszDest ? pszDest : addrConnect.ToString());
// Set to non-blocking
#ifdef WIN32
@@ -519,7 +521,7 @@ void CNode::CloseSocketDisconnect()
fDisconnect = true;
if (hSocket != INVALID_SOCKET)
{
- LogPrint("net", "disconnecting node %s\n", addrName.c_str());
+ LogPrint("net", "disconnecting node %s\n", addrName);
closesocket(hSocket);
hSocket = INVALID_SOCKET;
}
@@ -548,7 +550,7 @@ void CNode::PushVersion()
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));
- 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());
+ 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);
}
@@ -581,45 +583,30 @@ 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
{
- LogPrintf("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_t banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban
- LogPrintf("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
- LogPrintf("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);
@@ -965,12 +952,12 @@ void ThreadSocketHandler()
}
else if (CNode::IsBanned(addr))
{
- LogPrintf("connection from %s dropped (banned)\n", addr.ToString().c_str());
+ LogPrintf("connection from %s dropped (banned)\n", addr.ToString());
closesocket(hSocket);
}
else
{
- LogPrint("net", "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();
{
@@ -1151,7 +1138,7 @@ void ThreadMapPort()
if(r!=UPNPCOMMAND_SUCCESS)
LogPrintf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
- port.c_str(), port.c_str(), lanaddr, r, strupnperror(r));
+ port, port, lanaddr, r, strupnperror(r));
else
LogPrintf("UPnP Port Mapping successful.\n");;
@@ -1605,8 +1592,8 @@ 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().c_str());
- LogPrintf("%s\n", strError.c_str());
+ strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString());
+ LogPrintf("%s\n", strError);
return false;
}
@@ -1614,7 +1601,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());
- LogPrintf("%s\n", strError.c_str());
+ LogPrintf("%s\n", strError);
return false;
}
@@ -1638,7 +1625,7 @@ bool BindListenPort(const CService &addrBind, string& strError)
#endif
{
strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
- LogPrintf("%s\n", strError.c_str());
+ LogPrintf("%s\n", strError);
return false;
}
@@ -1666,19 +1653,19 @@ bool BindListenPort(const CService &addrBind, string& strError)
{
int nErr = WSAGetLastError();
if (nErr == WSAEADDRINUSE)
- strError = strprintf(_("Unable to bind to %s on this computer. Bitcoin is probably already running."), addrBind.ToString().c_str());
+ strError = strprintf(_("Unable to bind to %s on this computer. Bitcoin 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));
- LogPrintf("%s\n", strError.c_str());
+ strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString(), nErr, strerror(nErr));
+ LogPrintf("%s\n", strError);
return false;
}
- LogPrintf("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());
- LogPrintf("%s\n", strError.c_str());
+ LogPrintf("%s\n", strError);
return false;
}
@@ -1690,7 +1677,7 @@ bool BindListenPort(const CService &addrBind, string& strError)
return true;
}
-void static Discover()
+void static Discover(boost::thread_group& threadGroup)
{
if (!fDiscover)
return;
@@ -1725,7 +1712,7 @@ void static Discover()
struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
CNetAddr addr(s4->sin_addr);
if (AddLocal(addr, LOCAL_IF))
- LogPrintf("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)
@@ -1733,7 +1720,7 @@ void static Discover()
struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
CNetAddr addr(s6->sin6_addr);
if (AddLocal(addr, LOCAL_IF))
- LogPrintf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str());
+ LogPrintf("IPv6 %s: %s\n", ifa->ifa_name, addr.ToString());
}
#endif
}
@@ -1743,7 +1730,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)
@@ -1757,7 +1744,7 @@ 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
@@ -1942,3 +1929,103 @@ void CNode::Fuzz(int nChance)
// (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("CAddrman::Write() : open failed");
+
+ // Write and commit header, data
+ try {
+ fileout << ssPeers;
+ }
+ catch (std::exception &e) {
+ return error("CAddrman::Write() : I/O error");
+ }
+ FileCommit(fileout);
+ fileout.fclose();
+
+ // replace existing peers.dat, if any, with new peers.dat.XXXX
+ if (!RenameOver(pathTmp, pathAddr))
+ return error("CAddrman::Write() : Rename-into-place failed");
+
+ 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("CAddrman::Read() : open failed");
+
+ // use file size to size memory buffer
+ int fileSize = GetFilesize(filein);
+ 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("CAddrman::Read() 2 : I/O error or stream data corrupted");
+ }
+ 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("CAddrman::Read() : checksum mismatch; data corrupted");
+
+ 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("CAddrman::Read() : invalid network magic number");
+
+ // de-serialize address data into one CAddrMan object
+ ssPeers >> addr;
+ }
+ catch (std::exception &e) {
+ return error("CAddrman::Read() : I/O error or stream data corrupted");
+ }
+
+ return true;
+}