diff options
Diffstat (limited to 'src/net.cpp')
| -rw-r--r-- | src/net.cpp | 187 |
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; +} |