Changeset View
Changeset View
Standalone View
Standalone View
src/net.cpp
Show First 20 Lines • Show All 131 Lines • ▼ Show 20 Lines | |||||
static std::vector<CAddress> | static std::vector<CAddress> | ||||
convertSeed6(const std::vector<SeedSpec6> &vSeedsIn) { | convertSeed6(const std::vector<SeedSpec6> &vSeedsIn) { | ||||
// It'll only connect to one or two seed nodes because once it connects, | // It'll only connect to one or two seed nodes because once it connects, | ||||
// it'll get a pile of addresses with newer timestamps. Seed nodes are given | // it'll get a pile of addresses with newer timestamps. Seed nodes are given | ||||
// a random 'last seen time' of between one and two weeks ago. | // a random 'last seen time' of between one and two weeks ago. | ||||
const int64_t nOneWeek = 7 * 24 * 60 * 60; | const int64_t nOneWeek = 7 * 24 * 60 * 60; | ||||
std::vector<CAddress> vSeedsOut; | std::vector<CAddress> vSeedsOut; | ||||
vSeedsOut.reserve(vSeedsIn.size()); | vSeedsOut.reserve(vSeedsIn.size()); | ||||
for (std::vector<SeedSpec6>::const_iterator i(vSeedsIn.begin()); | for (const auto &seed_in : vSeedsIn) { | ||||
i != vSeedsIn.end(); ++i) { | |||||
struct in6_addr ip; | struct in6_addr ip; | ||||
memcpy(&ip, i->addr, sizeof(ip)); | memcpy(&ip, seed_in.addr, sizeof(ip)); | ||||
CAddress addr(CService(ip, i->port), NODE_NETWORK); | CAddress addr(CService(ip, seed_in.port), NODE_NETWORK); | ||||
addr.nTime = GetTime() - GetRand(nOneWeek) - nOneWeek; | addr.nTime = GetTime() - GetRand(nOneWeek) - nOneWeek; | ||||
vSeedsOut.push_back(addr); | vSeedsOut.push_back(addr); | ||||
} | } | ||||
return vSeedsOut; | return vSeedsOut; | ||||
} | } | ||||
// Get best local address for a particular peer as a CAddress. Otherwise, return | // Get best local address for a particular peer as a CAddress. Otherwise, return | ||||
// the unroutable 0.0.0.0 but filled in with the normal parameters, since the IP | // the unroutable 0.0.0.0 but filled in with the normal parameters, since the IP | ||||
// may be changed to a useful one by discovery. | // may be changed to a useful one by discovery. | ||||
CAddress GetLocalAddress(const CNetAddr *paddrPeer, | CAddress GetLocalAddress(const CNetAddr *paddrPeer, | ||||
ServiceFlags nLocalServices) { | ServiceFlags nLocalServices) { | ||||
CAddress ret(CService(CNetAddr(), GetListenPort()), NODE_NONE); | CAddress ret(CService(CNetAddr(), GetListenPort()), NODE_NONE); | ||||
CService addr; | CService addr; | ||||
if (GetLocal(addr, paddrPeer)) { | if (GetLocal(addr, paddrPeer)) { | ||||
ret = CAddress(addr, nLocalServices); | ret = CAddress(addr, nLocalServices); | ||||
} | } | ||||
ret.nTime = GetAdjustedTime(); | ret.nTime = GetAdjustedTime(); | ||||
return ret; | return ret; | ||||
} | } | ||||
int GetnScore(const CService &addr) { | static int GetnScore(const CService &addr) { | ||||
LOCK(cs_mapLocalHost); | LOCK(cs_mapLocalHost); | ||||
if (mapLocalHost.count(addr) == LOCAL_NONE) { | if (mapLocalHost.count(addr) == LOCAL_NONE) { | ||||
return 0; | return 0; | ||||
} | } | ||||
return mapLocalHost[addr].nScore; | return mapLocalHost[addr].nScore; | ||||
} | } | ||||
// Is our peer's addrLocal potentially useful as an external IP source? | // Is our peer's addrLocal potentially useful as an external IP source? | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | bool AddLocal(const CService &addr, int nScore) { | ||||
return true; | return true; | ||||
} | } | ||||
bool AddLocal(const CNetAddr &addr, int nScore) { | bool AddLocal(const CNetAddr &addr, int nScore) { | ||||
return AddLocal(CService(addr, GetListenPort()), nScore); | return AddLocal(CService(addr, GetListenPort()), nScore); | ||||
} | } | ||||
bool RemoveLocal(const CService &addr) { | void RemoveLocal(const CService &addr) { | ||||
LOCK(cs_mapLocalHost); | LOCK(cs_mapLocalHost); | ||||
LogPrintf("RemoveLocal(%s)\n", addr.ToString()); | LogPrintf("RemoveLocal(%s)\n", addr.ToString()); | ||||
mapLocalHost.erase(addr); | mapLocalHost.erase(addr); | ||||
return true; | |||||
} | } | ||||
/** | /** | ||||
* Make a particular network entirely off-limits (no automatic connects to it). | * Make a particular network entirely off-limits (no automatic connects to it). | ||||
*/ | */ | ||||
void SetLimited(enum Network net, bool fLimited) { | void SetLimited(enum Network net, bool fLimited) { | ||||
if (net == NET_UNROUTABLE || net == NET_INTERNAL) { | if (net == NET_UNROUTABLE || net == NET_INTERNAL) { | ||||
return; | return; | ||||
Show All 37 Lines | |||||
bool IsReachable(const CNetAddr &addr) { | bool IsReachable(const CNetAddr &addr) { | ||||
enum Network net = addr.GetNetwork(); | enum Network net = addr.GetNetwork(); | ||||
return IsReachable(net); | return IsReachable(net); | ||||
} | } | ||||
CNode *CConnman::FindNode(const CNetAddr &ip) { | CNode *CConnman::FindNode(const CNetAddr &ip) { | ||||
LOCK(cs_vNodes); | LOCK(cs_vNodes); | ||||
for (CNode *pnode : vNodes) { | for (CNode *pnode : vNodes) { | ||||
if ((CNetAddr)pnode->addr == ip) { | if (static_cast<CNetAddr>(pnode->addr) == ip) { | ||||
return pnode; | return pnode; | ||||
} | } | ||||
} | } | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
CNode *CConnman::FindNode(const CSubNet &subNet) { | CNode *CConnman::FindNode(const CSubNet &subNet) { | ||||
LOCK(cs_vNodes); | LOCK(cs_vNodes); | ||||
for (CNode *pnode : vNodes) { | for (CNode *pnode : vNodes) { | ||||
if (subNet.Match((CNetAddr)pnode->addr)) { | if (subNet.Match(static_cast<CNetAddr>(pnode->addr))) { | ||||
return pnode; | return pnode; | ||||
} | } | ||||
} | } | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
CNode *CConnman::FindNode(const std::string &addrName) { | CNode *CConnman::FindNode(const std::string &addrName) { | ||||
LOCK(cs_vNodes); | LOCK(cs_vNodes); | ||||
for (CNode *pnode : vNodes) { | for (CNode *pnode : vNodes) { | ||||
if (pnode->GetAddrName() == addrName) { | if (pnode->GetAddrName() == addrName) { | ||||
return pnode; | return pnode; | ||||
} | } | ||||
} | } | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
CNode *CConnman::FindNode(const CService &addr) { | CNode *CConnman::FindNode(const CService &addr) { | ||||
LOCK(cs_vNodes); | LOCK(cs_vNodes); | ||||
for (CNode *pnode : vNodes) { | for (CNode *pnode : vNodes) { | ||||
if ((CService)pnode->addr == addr) { | if (static_cast<CService>(pnode->addr) == addr) { | ||||
return pnode; | return pnode; | ||||
} | } | ||||
} | } | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
bool CConnman::CheckIncomingNonce(uint64_t nonce) { | bool CConnman::CheckIncomingNonce(uint64_t nonce) { | ||||
LOCK(cs_vNodes); | LOCK(cs_vNodes); | ||||
for (CNode *pnode : vNodes) { | for (const CNode *pnode : vNodes) { | ||||
if (!pnode->fSuccessfullyConnected && !pnode->fInbound && | if (!pnode->fSuccessfullyConnected && !pnode->fInbound && | ||||
pnode->GetLocalNonce() == nonce) | pnode->GetLocalNonce() == nonce) | ||||
return false; | return false; | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
/** Get the bind address for a socket as CAddress */ | /** Get the bind address for a socket as CAddress */ | ||||
Show All 15 Lines | |||||
CNode *CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, | CNode *CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, | ||||
bool fCountFailure) { | bool fCountFailure) { | ||||
if (pszDest == nullptr) { | if (pszDest == nullptr) { | ||||
if (IsLocal(addrConnect)) { | if (IsLocal(addrConnect)) { | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
// Look for an existing connection | // Look for an existing connection | ||||
CNode *pnode = FindNode((CService)addrConnect); | CNode *pnode = FindNode(static_cast<CService>(addrConnect)); | ||||
if (pnode) { | if (pnode) { | ||||
LogPrintf("Failed to open new connection, already connected\n"); | LogPrintf("Failed to open new connection, already connected\n"); | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
} | } | ||||
/// debug print | /// debug print | ||||
LogPrint(BCLog::NET, "trying connection %s lastseen=%.1fhrs\n", | LogPrint(BCLog::NET, "trying connection %s lastseen=%.1fhrs\n", | ||||
▲ Show 20 Lines • Show All 193 Lines • ▼ Show 20 Lines | void CConnman::Ban(const CSubNet &subNet, const BanReason &banReason, | ||||
if (clientInterface) { | if (clientInterface) { | ||||
clientInterface->BannedListChanged(); | clientInterface->BannedListChanged(); | ||||
} | } | ||||
{ | { | ||||
LOCK(cs_vNodes); | LOCK(cs_vNodes); | ||||
for (CNode *pnode : vNodes) { | for (CNode *pnode : vNodes) { | ||||
if (subNet.Match((CNetAddr)pnode->addr)) { | if (subNet.Match(static_cast<CNetAddr>(pnode->addr))) { | ||||
pnode->fDisconnect = true; | pnode->fDisconnect = true; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
if (banReason == BanReasonManuallyAdded) { | if (banReason == BanReasonManuallyAdded) { | ||||
// Store banlist to disk immediately if user requested ban. | // Store banlist to disk immediately if user requested ban. | ||||
DumpBanlist(); | DumpBanlist(); | ||||
▲ Show 20 Lines • Show All 532 Lines • ▼ Show 20 Lines | bool CConnman::AttemptToEvictConnection() { | ||||
} | } | ||||
// Reduce to the network group with the most connections | // Reduce to the network group with the most connections | ||||
vEvictionCandidates = std::move(mapNetGroupNodes[naMostConnections]); | vEvictionCandidates = std::move(mapNetGroupNodes[naMostConnections]); | ||||
// Disconnect from the network group with the most connections | // Disconnect from the network group with the most connections | ||||
NodeId evicted = vEvictionCandidates.front().id; | NodeId evicted = vEvictionCandidates.front().id; | ||||
LOCK(cs_vNodes); | LOCK(cs_vNodes); | ||||
for (std::vector<CNode *>::const_iterator it(vNodes.begin()); | for (CNode *pnode : vNodes) { | ||||
it != vNodes.end(); ++it) { | if (pnode->GetId() == evicted) { | ||||
if ((*it)->GetId() == evicted) { | pnode->fDisconnect = true; | ||||
(*it)->fDisconnect = true; | |||||
return true; | return true; | ||||
} | } | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
void CConnman::AcceptConnection(const ListenSocket &hListenSocket) { | void CConnman::AcceptConnection(const ListenSocket &hListenSocket) { | ||||
struct sockaddr_storage sockaddr; | struct sockaddr_storage sockaddr; | ||||
socklen_t len = sizeof(sockaddr); | socklen_t len = sizeof(sockaddr); | ||||
SOCKET hSocket = | SOCKET hSocket = | ||||
accept(hListenSocket.socket, (struct sockaddr *)&sockaddr, &len); | accept(hListenSocket.socket, (struct sockaddr *)&sockaddr, &len); | ||||
CAddress addr; | CAddress addr; | ||||
int nInbound = 0; | int nInbound = 0; | ||||
int nMaxInbound = nMaxConnections - (nMaxOutbound + nMaxFeeler); | int nMaxInbound = nMaxConnections - (nMaxOutbound + nMaxFeeler); | ||||
if (hSocket != INVALID_SOCKET) { | if (hSocket != INVALID_SOCKET) { | ||||
if (!addr.SetSockAddr((const struct sockaddr *)&sockaddr)) { | if (!addr.SetSockAddr((const struct sockaddr *)&sockaddr)) { | ||||
LogPrintf("Warning: Unknown socket family\n"); | LogPrintf("Warning: Unknown socket family\n"); | ||||
} | } | ||||
} | } | ||||
bool whitelisted = hListenSocket.whitelisted || IsWhitelistedRange(addr); | bool whitelisted = hListenSocket.whitelisted || IsWhitelistedRange(addr); | ||||
{ | { | ||||
LOCK(cs_vNodes); | LOCK(cs_vNodes); | ||||
for (CNode *pnode : vNodes) { | for (const CNode *pnode : vNodes) { | ||||
if (pnode->fInbound) { | if (pnode->fInbound) { | ||||
nInbound++; | nInbound++; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
if (hSocket == INVALID_SOCKET) { | if (hSocket == INVALID_SOCKET) { | ||||
int nErr = WSAGetLastError(); | int nErr = WSAGetLastError(); | ||||
▲ Show 20 Lines • Show All 358 Lines • ▼ Show 20 Lines | while (!interruptNet) { | ||||
} else if (pnode->nPingNonceSent && | } else if (pnode->nPingNonceSent && | ||||
pnode->nPingUsecStart + TIMEOUT_INTERVAL * 1000000 < | pnode->nPingUsecStart + TIMEOUT_INTERVAL * 1000000 < | ||||
GetTimeMicros()) { | GetTimeMicros()) { | ||||
LogPrintf("ping timeout: %fs\n", | LogPrintf("ping timeout: %fs\n", | ||||
0.000001 * | 0.000001 * | ||||
(GetTimeMicros() - pnode->nPingUsecStart)); | (GetTimeMicros() - pnode->nPingUsecStart)); | ||||
pnode->fDisconnect = true; | pnode->fDisconnect = true; | ||||
} else if (!pnode->fSuccessfullyConnected) { | } else if (!pnode->fSuccessfullyConnected) { | ||||
LogPrintf("version handshake timeout from %d\n", | LogPrint(BCLog::NET, "version handshake timeout from %d\n", | ||||
pnode->GetId()); | pnode->GetId()); | ||||
pnode->fDisconnect = true; | pnode->fDisconnect = true; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
{ | { | ||||
LOCK(cs_vNodes); | LOCK(cs_vNodes); | ||||
for (CNode *pnode : vNodesCopy) { | for (CNode *pnode : vNodesCopy) { | ||||
pnode->Release(); | pnode->Release(); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
void CConnman::WakeMessageHandler() { | void CConnman::WakeMessageHandler() { | ||||
{ | { | ||||
std::lock_guard<std::mutex> lock(mutexMsgProc); | std::lock_guard<std::mutex> lock(mutexMsgProc); | ||||
fMsgProcWake = true; | fMsgProcWake = true; | ||||
} | } | ||||
condMsgProc.notify_one(); | condMsgProc.notify_one(); | ||||
} | } | ||||
#ifdef USE_UPNP | #ifdef USE_UPNP | ||||
static CThreadInterrupt g_upnp_interrupt; | static CThreadInterrupt g_upnp_interrupt; | ||||
static std::thread g_upnp_thread; | static std::thread g_upnp_thread; | ||||
void ThreadMapPort() { | static void ThreadMapPort() { | ||||
std::string port = strprintf("%u", GetListenPort()); | std::string port = strprintf("%u", GetListenPort()); | ||||
const char *multicastif = 0; | const char *multicastif = nullptr; | ||||
const char *minissdpdpath = 0; | const char *minissdpdpath = nullptr; | ||||
struct UPNPDev *devlist = 0; | struct UPNPDev *devlist = nullptr; | ||||
char lanaddr[64]; | char lanaddr[64]; | ||||
#ifndef UPNPDISCOVER_SUCCESS | #ifndef UPNPDISCOVER_SUCCESS | ||||
/* miniupnpc 1.5 */ | /* miniupnpc 1.5 */ | ||||
devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0); | devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0); | ||||
#elif MINIUPNPC_API_VERSION < 14 | #elif MINIUPNPC_API_VERSION < 14 | ||||
/* miniupnpc 1.6 */ | /* miniupnpc 1.6 */ | ||||
int error = 0; | int error = 0; | ||||
▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | #endif | ||||
if (r != UPNPCOMMAND_SUCCESS) { | if (r != UPNPCOMMAND_SUCCESS) { | ||||
LogPrintf( | LogPrintf( | ||||
"AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", | "AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", | ||||
port, port, lanaddr, r, strupnperror(r)); | port, port, lanaddr, r, strupnperror(r)); | ||||
} else { | } else { | ||||
LogPrintf("UPnP Port Mapping successful.\n"); | LogPrintf("UPnP Port Mapping successful.\n"); | ||||
} | } | ||||
} | } while (g_upnp_interrupt.sleep_for(std::chrono::minutes(20))); | ||||
while (g_upnp_interrupt.sleep_for(std::chrono::minutes(20))); | |||||
r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, | r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, | ||||
port.c_str(), "TCP", 0); | port.c_str(), "TCP", 0); | ||||
LogPrintf("UPNP_DeletePortMapping() returned: %d\n", r); | LogPrintf("UPNP_DeletePortMapping() returned: %d\n", r); | ||||
freeUPNPDevlist(devlist); | freeUPNPDevlist(devlist); | ||||
devlist = nullptr; | devlist = nullptr; | ||||
FreeUPNPUrls(&urls); | FreeUPNPUrls(&urls); | ||||
} else { | } else { | ||||
LogPrintf("No valid UPnP IGDs found\n"); | LogPrintf("No valid UPnP IGDs found\n"); | ||||
freeUPNPDevlist(devlist); | freeUPNPDevlist(devlist); | ||||
devlist = 0; | devlist = nullptr; | ||||
if (r != 0) { | if (r != 0) { | ||||
FreeUPNPUrls(&urls); | FreeUPNPUrls(&urls); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
void StartMapPort() { | void StartMapPort() { | ||||
if (!g_upnp_thread.joinable()) { | if (!g_upnp_thread.joinable()) { | ||||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | void CConnman::ThreadDNSAddressSeed() { | ||||
if ((addrman.size() > 0) && | if ((addrman.size() > 0) && | ||||
(!gArgs.GetBoolArg("-forcednsseed", DEFAULT_FORCEDNSSEED))) { | (!gArgs.GetBoolArg("-forcednsseed", DEFAULT_FORCEDNSSEED))) { | ||||
if (!interruptNet.sleep_for(std::chrono::seconds(11))) { | if (!interruptNet.sleep_for(std::chrono::seconds(11))) { | ||||
return; | return; | ||||
} | } | ||||
LOCK(cs_vNodes); | LOCK(cs_vNodes); | ||||
int nRelevant = 0; | int nRelevant = 0; | ||||
for (auto pnode : vNodes) { | for (const CNode *pnode : vNodes) { | ||||
nRelevant += pnode->fSuccessfullyConnected && !pnode->fFeeler && | nRelevant += pnode->fSuccessfullyConnected && !pnode->fFeeler && | ||||
!pnode->fOneShot && !pnode->m_manual_connection && | !pnode->fOneShot && !pnode->m_manual_connection && | ||||
!pnode->fInbound; | !pnode->fInbound; | ||||
} | } | ||||
if (nRelevant >= 2) { | if (nRelevant >= 2) { | ||||
LogPrintf("P2P peers available. Skipped DNS seeding.\n"); | LogPrintf("P2P peers available. Skipped DNS seeding.\n"); | ||||
return; | return; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | |||||
// soon (eg one-shots and feelers). | // soon (eg one-shots and feelers). | ||||
// Also exclude peers that haven't finished initial connection handshake yet (so | // Also exclude peers that haven't finished initial connection handshake yet (so | ||||
// that we don't decide we're over our desired connection limit, and then evict | // that we don't decide we're over our desired connection limit, and then evict | ||||
// some peer that has finished the handshake). | // some peer that has finished the handshake). | ||||
int CConnman::GetExtraOutboundCount() { | int CConnman::GetExtraOutboundCount() { | ||||
int nOutbound = 0; | int nOutbound = 0; | ||||
{ | { | ||||
LOCK(cs_vNodes); | LOCK(cs_vNodes); | ||||
for (CNode *pnode : vNodes) { | for (const CNode *pnode : vNodes) { | ||||
if (!pnode->fInbound && !pnode->m_manual_connection && | if (!pnode->fInbound && !pnode->m_manual_connection && | ||||
!pnode->fFeeler && !pnode->fDisconnect && !pnode->fOneShot && | !pnode->fFeeler && !pnode->fDisconnect && !pnode->fOneShot && | ||||
pnode->fSuccessfullyConnected) { | pnode->fSuccessfullyConnected) { | ||||
++nOutbound; | ++nOutbound; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return std::max(nOutbound - nMaxOutbound, 0); | return std::max(nOutbound - nMaxOutbound, 0); | ||||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | while (!interruptNet) { | ||||
// Only connect out to one peer per network group (/16 for IPv4). Do | // Only connect out to one peer per network group (/16 for IPv4). Do | ||||
// this here so we don't have to critsect vNodes inside mapAddresses | // this here so we don't have to critsect vNodes inside mapAddresses | ||||
// critsect. | // critsect. | ||||
int nOutbound = 0; | int nOutbound = 0; | ||||
std::set<std::vector<uint8_t>> setConnected; | std::set<std::vector<uint8_t>> setConnected; | ||||
{ | { | ||||
LOCK(cs_vNodes); | LOCK(cs_vNodes); | ||||
for (CNode *pnode : vNodes) { | for (const CNode *pnode : vNodes) { | ||||
if (!pnode->fInbound && !pnode->m_manual_connection) { | if (!pnode->fInbound && !pnode->m_manual_connection) { | ||||
// Netgroups for inbound and addnode peers are not excluded | // Netgroups for inbound and addnode peers are not excluded | ||||
// because our goal here is to not use multiple of our | // because our goal here is to not use multiple of our | ||||
// limited outbound slots on a single netgroup but inbound | // limited outbound slots on a single netgroup but inbound | ||||
// and addnode peers do not use our outbound slots. Inbound | // and addnode peers do not use our outbound slots. Inbound | ||||
// peers also have the added issue that they're attacker | // peers also have the added issue that they're attacker | ||||
// controlled and could be used to prevent us from | // controlled and could be used to prevent us from | ||||
// connecting to particular hosts if we used them here. | // connecting to particular hosts if we used them here. | ||||
▲ Show 20 Lines • Show All 104 Lines • ▼ Show 20 Lines | |||||
std::vector<AddedNodeInfo> CConnman::GetAddedNodeInfo() { | std::vector<AddedNodeInfo> CConnman::GetAddedNodeInfo() { | ||||
std::vector<AddedNodeInfo> ret; | std::vector<AddedNodeInfo> ret; | ||||
std::list<std::string> lAddresses(0); | std::list<std::string> lAddresses(0); | ||||
{ | { | ||||
LOCK(cs_vAddedNodes); | LOCK(cs_vAddedNodes); | ||||
ret.reserve(vAddedNodes.size()); | ret.reserve(vAddedNodes.size()); | ||||
for (const std::string &strAddNode : vAddedNodes) { | std::copy(vAddedNodes.cbegin(), vAddedNodes.cend(), | ||||
lAddresses.push_back(strAddNode); | std::back_inserter(lAddresses)); | ||||
} | |||||
} | } | ||||
// Build a map of all already connected addresses (by IP:port and by name) | // Build a map of all already connected addresses (by IP:port and by name) | ||||
// to inbound/outbound and resolved CService | // to inbound/outbound and resolved CService | ||||
std::map<CService, bool> mapConnected; | std::map<CService, bool> mapConnected; | ||||
std::map<std::string, std::pair<bool, CService>> mapConnectedByName; | std::map<std::string, std::pair<bool, CService>> mapConnectedByName; | ||||
{ | { | ||||
LOCK(cs_vNodes); | LOCK(cs_vNodes); | ||||
▲ Show 20 Lines • Show All 192 Lines • ▼ Show 20 Lines | bool CConnman::BindListenPort(const CService &addrBind, std::string &strError, | ||||
SOCKET hListenSocket = CreateSocket(addrBind); | SOCKET hListenSocket = CreateSocket(addrBind); | ||||
if (hListenSocket == INVALID_SOCKET) { | if (hListenSocket == INVALID_SOCKET) { | ||||
strError = strprintf("Error: Couldn't open socket for incoming " | strError = strprintf("Error: Couldn't open socket for incoming " | ||||
"connections (socket returned error %s)", | "connections (socket returned error %s)", | ||||
NetworkErrorString(WSAGetLastError())); | NetworkErrorString(WSAGetLastError())); | ||||
LogPrintf("%s\n", strError); | LogPrintf("%s\n", strError); | ||||
return false; | return false; | ||||
} | } | ||||
// Allow binding if the port is still in TIME_WAIT state after | // Allow binding if the port is still in TIME_WAIT state after | ||||
// the program was closed and restarted. | // the program was closed and restarted. | ||||
setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (sockopt_arg_type)&nOne, | setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (sockopt_arg_type)&nOne, | ||||
sizeof(int)); | sizeof(int)); | ||||
// Some systems don't have IPV6_V6ONLY but are always v6only; others do have | // 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 | // the option and enable it by default or not. Try to enable it, if | ||||
// possible. | // possible. | ||||
▲ Show 20 Lines • Show All 181 Lines • ▼ Show 20 Lines | if (fListen && !InitBinds(connOptions.vBinds, connOptions.vWhiteBinds)) { | ||||
return false; | return false; | ||||
} | } | ||||
for (const auto &strDest : connOptions.vSeedNodes) { | for (const auto &strDest : connOptions.vSeedNodes) { | ||||
AddOneShot(strDest); | AddOneShot(strDest); | ||||
} | } | ||||
if (clientInterface) { | if (clientInterface) { | ||||
clientInterface->InitMessage(_("Loading addresses...")); | clientInterface->InitMessage(_("Loading P2P addresses...")); | ||||
} | } | ||||
// Load addresses from peers.dat | // Load addresses from peers.dat | ||||
int64_t nStart = GetTimeMillis(); | int64_t nStart = GetTimeMillis(); | ||||
{ | { | ||||
CAddrDB adb(config->GetChainParams()); | CAddrDB adb(config->GetChainParams()); | ||||
if (adb.Read(addrman)) { | if (adb.Read(addrman)) { | ||||
LogPrintf("Loaded %i addresses from peers.dat %dms\n", | LogPrintf("Loaded %i addresses from peers.dat %dms\n", | ||||
addrman.size(), GetTimeMillis() - nStart); | addrman.size(), GetTimeMillis() - nStart); | ||||
▲ Show 20 Lines • Show All 230 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
std::vector<CAddress> CConnman::GetAddresses() { | std::vector<CAddress> CConnman::GetAddresses() { | ||||
return addrman.GetAddr(); | return addrman.GetAddr(); | ||||
} | } | ||||
bool CConnman::AddNode(const std::string &strNode) { | bool CConnman::AddNode(const std::string &strNode) { | ||||
LOCK(cs_vAddedNodes); | LOCK(cs_vAddedNodes); | ||||
for (std::vector<std::string>::const_iterator it = vAddedNodes.begin(); | for (const std::string &it : vAddedNodes) { | ||||
it != vAddedNodes.end(); ++it) { | if (strNode == it) { | ||||
if (strNode == *it) { | |||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
vAddedNodes.push_back(strNode); | vAddedNodes.push_back(strNode); | ||||
return true; | return true; | ||||
} | } | ||||
Show All 12 Lines | |||||
size_t CConnman::GetNodeCount(NumConnections flags) { | size_t CConnman::GetNodeCount(NumConnections flags) { | ||||
LOCK(cs_vNodes); | LOCK(cs_vNodes); | ||||
// Shortcut if we want total | // Shortcut if we want total | ||||
if (flags == CConnman::CONNECTIONS_ALL) { | if (flags == CConnman::CONNECTIONS_ALL) { | ||||
return vNodes.size(); | return vNodes.size(); | ||||
} | } | ||||
int nNum = 0; | int nNum = 0; | ||||
for (std::vector<CNode *>::const_iterator it = vNodes.begin(); | for (const auto &pnode : vNodes) { | ||||
it != vNodes.end(); ++it) { | if (flags & (pnode->fInbound ? CONNECTIONS_IN : CONNECTIONS_OUT)) { | ||||
if (flags & ((*it)->fInbound ? CONNECTIONS_IN : CONNECTIONS_OUT)) { | |||||
nNum++; | nNum++; | ||||
} | } | ||||
} | } | ||||
return nNum; | return nNum; | ||||
} | } | ||||
void CConnman::GetNodeStats(std::vector<CNodeStats> &vstats) { | void CConnman::GetNodeStats(std::vector<CNodeStats> &vstats) { | ||||
▲ Show 20 Lines • Show All 331 Lines • ▼ Show 20 Lines | |||||
CSipHasher CConnman::GetDeterministicRandomizer(uint64_t id) const { | CSipHasher CConnman::GetDeterministicRandomizer(uint64_t id) const { | ||||
return CSipHasher(nSeed0, nSeed1).Write(id); | return CSipHasher(nSeed0, nSeed1).Write(id); | ||||
} | } | ||||
uint64_t CConnman::CalculateKeyedNetGroup(const CAddress &ad) const { | uint64_t CConnman::CalculateKeyedNetGroup(const CAddress &ad) const { | ||||
std::vector<uint8_t> vchNetGroup(ad.GetGroup()); | std::vector<uint8_t> vchNetGroup(ad.GetGroup()); | ||||
return GetDeterministicRandomizer(RANDOMIZER_ID_NETGROUP) | return GetDeterministicRandomizer(RANDOMIZER_ID_NETGROUP) | ||||
.Write(&vchNetGroup[0], vchNetGroup.size()) | .Write(vchNetGroup.data(), vchNetGroup.size()) | ||||
.Finalize(); | .Finalize(); | ||||
} | } | ||||
/** | /** | ||||
* This function convert MaxBlockSize from byte to | * This function convert MaxBlockSize from byte to | ||||
* MB with a decimal precision one digit rounded down | * MB with a decimal precision one digit rounded down | ||||
* E.g. | * E.g. | ||||
* 1660000 -> 1.6 | * 1660000 -> 1.6 | ||||
▲ Show 20 Lines • Show All 54 Lines • Show Last 20 Lines |