Changeset View
Changeset View
Standalone View
Standalone View
src/net.cpp
Show First 20 Lines • Show All 207 Lines • ▼ Show 20 Lines | bool AddLocal(const CService &addr, int nScore) { | ||||
if (!fDiscover && nScore < LOCAL_MANUAL) { | if (!fDiscover && nScore < LOCAL_MANUAL) { | ||||
return false; | return false; | ||||
} | } | ||||
if (IsLimited(addr)) { | if (IsLimited(addr)) { | ||||
return false; | return false; | ||||
} | } | ||||
LogPrintf("AddLocal(%s,%i)\n", addr.ToString(), nScore); | LogPrint(BCLog::NET, "AddLocal(%s,%i)\n", addr.ToString(), nScore); | ||||
{ | { | ||||
LOCK(cs_mapLocalHost); | LOCK(cs_mapLocalHost); | ||||
bool fAlready = mapLocalHost.count(addr) > 0; | bool fAlready = mapLocalHost.count(addr) > 0; | ||||
LocalServiceInfo &info = mapLocalHost[addr]; | LocalServiceInfo &info = mapLocalHost[addr]; | ||||
if (!fAlready || nScore >= info.nScore) { | if (!fAlready || nScore >= info.nScore) { | ||||
info.nScore = nScore + (fAlready ? 1 : 0); | info.nScore = nScore + (fAlready ? 1 : 0); | ||||
info.nPort = addr.GetPort(); | info.nPort = addr.GetPort(); | ||||
} | } | ||||
} | } | ||||
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); | ||||
} | } | ||||
void RemoveLocal(const CService &addr) { | void RemoveLocal(const CService &addr) { | ||||
LOCK(cs_mapLocalHost); | LOCK(cs_mapLocalHost); | ||||
LogPrintf("RemoveLocal(%s)\n", addr.ToString()); | LogPrint(BCLog::NET, "RemoveLocal(%s)\n", addr.ToString()); | ||||
mapLocalHost.erase(addr); | mapLocalHost.erase(addr); | ||||
} | } | ||||
/** | /** | ||||
* 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) { | ||||
▲ Show 20 Lines • Show All 111 Lines • ▼ Show 20 Lines | CNode *CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, | ||||
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(static_cast<CService>(addrConnect)); | CNode *pnode = FindNode(static_cast<CService>(addrConnect)); | ||||
if (pnode) { | if (pnode) { | ||||
LogPrintf("Failed to open new connection, already connected\n"); | LogPrint(BCLog::NET, | ||||
"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", | ||||
pszDest ? pszDest : addrConnect.ToString(), | pszDest ? pszDest : addrConnect.ToString(), | ||||
pszDest | pszDest | ||||
Show All 19 Lines | if (pszDest) { | ||||
// pszDest resolved to. In that case, drop the connection that was | // pszDest resolved to. In that case, drop the connection that was | ||||
// just created, and return the existing CNode instead. Also store | // just created, and return the existing CNode instead. Also store | ||||
// the name we used to connect in that CNode, so that future | // the name we used to connect in that CNode, so that future | ||||
// FindNode() calls to that name catch this early. | // FindNode() calls to that name catch this early. | ||||
LOCK(cs_vNodes); | LOCK(cs_vNodes); | ||||
CNode *pnode = FindNode(static_cast<CService>(addrConnect)); | CNode *pnode = FindNode(static_cast<CService>(addrConnect)); | ||||
if (pnode) { | if (pnode) { | ||||
pnode->MaybeSetAddrName(std::string(pszDest)); | pnode->MaybeSetAddrName(std::string(pszDest)); | ||||
LogPrintf("Failed to open new connection, already connected\n"); | LogPrint(BCLog::NET, | ||||
"Failed to open new connection, already connected\n"); | |||||
return nullptr; | return nullptr; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// Connect | // Connect | ||||
bool connected = false; | bool connected = false; | ||||
SOCKET hSocket = INVALID_SOCKET; | SOCKET hSocket = INVALID_SOCKET; | ||||
▲ Show 20 Lines • Show All 523 Lines • ▼ Show 20 Lines | for (const auto &data : pnode->vSendMsg) { | ||||
break; | break; | ||||
} | } | ||||
if (nBytes < 0) { | if (nBytes < 0) { | ||||
// error | // error | ||||
int nErr = WSAGetLastError(); | int nErr = WSAGetLastError(); | ||||
if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && | if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && | ||||
nErr != WSAEINTR && nErr != WSAEINPROGRESS) { | nErr != WSAEINTR && nErr != WSAEINPROGRESS) { | ||||
LogPrintf("socket send error %s\n", NetworkErrorString(nErr)); | LogPrint(BCLog::NET, "socket send error %s\n", | ||||
NetworkErrorString(nErr)); | |||||
pnode->CloseSocketDisconnect(); | pnode->CloseSocketDisconnect(); | ||||
} | } | ||||
break; | break; | ||||
} | } | ||||
assert(nBytes > 0); | assert(nBytes > 0); | ||||
pnode->nLastSend = GetSystemTimeInSeconds(); | pnode->nLastSend = GetSystemTimeInSeconds(); | ||||
▲ Show 20 Lines • Show All 193 Lines • ▼ Show 20 Lines | void CConnman::AcceptConnection(const ListenSocket &hListenSocket) { | ||||
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"); | LogPrint(BCLog::NET, "Warning: Unknown socket family\n"); | ||||
} | } | ||||
} | } | ||||
bool whitelisted = hListenSocket.whitelisted || IsWhitelistedRange(addr); | bool whitelisted = hListenSocket.whitelisted || IsWhitelistedRange(addr); | ||||
{ | { | ||||
LOCK(cs_vNodes); | LOCK(cs_vNodes); | ||||
for (const 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(); | ||||
if (nErr != WSAEWOULDBLOCK) { | if (nErr != WSAEWOULDBLOCK) { | ||||
LogPrintf("socket error accept failed: %s\n", | LogPrint(BCLog::NET, "socket error accept failed: %s\n", | ||||
NetworkErrorString(nErr)); | NetworkErrorString(nErr)); | ||||
} | } | ||||
return; | return; | ||||
} | } | ||||
if (!fNetworkActive) { | if (!fNetworkActive) { | ||||
LogPrintf("connection from %s dropped: not accepting new connections\n", | LogPrint(BCLog::NET, | ||||
"connection from %s dropped: not accepting new connections\n", | |||||
addr.ToString()); | addr.ToString()); | ||||
CloseSocket(hSocket); | CloseSocket(hSocket); | ||||
return; | return; | ||||
} | } | ||||
if (!IsSelectableSocket(hSocket)) { | if (!IsSelectableSocket(hSocket)) { | ||||
LogPrintf("connection from %s dropped: non-selectable socket\n", | LogPrint(BCLog::NET, | ||||
"connection from %s dropped: non-selectable socket\n", | |||||
addr.ToString()); | addr.ToString()); | ||||
CloseSocket(hSocket); | CloseSocket(hSocket); | ||||
return; | return; | ||||
} | } | ||||
// According to the internet TCP_NODELAY is not carried into accepted | // According to the internet TCP_NODELAY is not carried into accepted | ||||
// sockets on all platforms. Set it again here just to be sure. | // sockets on all platforms. Set it again here just to be sure. | ||||
SetSocketNoDelay(hSocket); | SetSocketNoDelay(hSocket); | ||||
▲ Show 20 Lines • Show All 179 Lines • ▼ Show 20 Lines | while (!interruptNet) { | ||||
&fdsetSend, &fdsetError, &timeout); | &fdsetSend, &fdsetError, &timeout); | ||||
if (interruptNet) { | if (interruptNet) { | ||||
return; | return; | ||||
} | } | ||||
if (nSelect == SOCKET_ERROR) { | if (nSelect == SOCKET_ERROR) { | ||||
if (have_fds) { | if (have_fds) { | ||||
int nErr = WSAGetLastError(); | int nErr = WSAGetLastError(); | ||||
LogPrintf("socket select error %s\n", NetworkErrorString(nErr)); | LogPrint(BCLog::NET, "socket select error %s\n", | ||||
NetworkErrorString(nErr)); | |||||
for (unsigned int i = 0; i <= hSocketMax; i++) { | for (unsigned int i = 0; i <= hSocketMax; i++) { | ||||
FD_SET(i, &fdsetRecv); | FD_SET(i, &fdsetRecv); | ||||
} | } | ||||
} | } | ||||
FD_ZERO(&fdsetSend); | FD_ZERO(&fdsetSend); | ||||
FD_ZERO(&fdsetError); | FD_ZERO(&fdsetError); | ||||
if (!interruptNet.sleep_for( | if (!interruptNet.sleep_for( | ||||
std::chrono::milliseconds(timeout.tv_usec / 1000))) { | std::chrono::milliseconds(timeout.tv_usec / 1000))) { | ||||
▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | while (!interruptNet) { | ||||
} | } | ||||
pnode->CloseSocketDisconnect(); | pnode->CloseSocketDisconnect(); | ||||
} else if (nBytes < 0) { | } else if (nBytes < 0) { | ||||
// error | // error | ||||
int nErr = WSAGetLastError(); | int nErr = WSAGetLastError(); | ||||
if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && | if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && | ||||
nErr != WSAEINTR && nErr != WSAEINPROGRESS) { | nErr != WSAEINTR && nErr != WSAEINPROGRESS) { | ||||
if (!pnode->fDisconnect) { | if (!pnode->fDisconnect) { | ||||
LogPrintf("socket recv error %s\n", | LogPrint(BCLog::NET, "socket recv error %s\n", | ||||
NetworkErrorString(nErr)); | NetworkErrorString(nErr)); | ||||
} | } | ||||
pnode->CloseSocketDisconnect(); | pnode->CloseSocketDisconnect(); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// | // | ||||
// Send | // Send | ||||
Show All 13 Lines | while (!interruptNet) { | ||||
if (nTime - pnode->nTimeConnected > 60) { | if (nTime - pnode->nTimeConnected > 60) { | ||||
if (pnode->nLastRecv == 0 || pnode->nLastSend == 0) { | if (pnode->nLastRecv == 0 || pnode->nLastSend == 0) { | ||||
LogPrint(BCLog::NET, "socket no message in first 60 " | LogPrint(BCLog::NET, "socket no message in first 60 " | ||||
"seconds, %d %d from %d\n", | "seconds, %d %d from %d\n", | ||||
pnode->nLastRecv != 0, pnode->nLastSend != 0, | pnode->nLastRecv != 0, pnode->nLastSend != 0, | ||||
pnode->GetId()); | pnode->GetId()); | ||||
pnode->fDisconnect = true; | pnode->fDisconnect = true; | ||||
} else if (nTime - pnode->nLastSend > TIMEOUT_INTERVAL) { | } else if (nTime - pnode->nLastSend > TIMEOUT_INTERVAL) { | ||||
LogPrintf("socket sending timeout: %is\n", | LogPrint(BCLog::NET, "socket sending timeout: %is\n", | ||||
nTime - pnode->nLastSend); | nTime - pnode->nLastSend); | ||||
pnode->fDisconnect = true; | pnode->fDisconnect = true; | ||||
} else if (nTime - pnode->nLastRecv > | } else if (nTime - pnode->nLastRecv > | ||||
(pnode->nVersion > BIP0031_VERSION ? TIMEOUT_INTERVAL | (pnode->nVersion > BIP0031_VERSION ? TIMEOUT_INTERVAL | ||||
: 90 * 60)) { | : 90 * 60)) { | ||||
LogPrintf("socket receive timeout: %is\n", | LogPrint(BCLog::NET, "socket receive timeout: %is\n", | ||||
nTime - pnode->nLastRecv); | nTime - pnode->nLastRecv); | ||||
pnode->fDisconnect = true; | pnode->fDisconnect = true; | ||||
} 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", | LogPrint(BCLog::NET, "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) { | ||||
LogPrint(BCLog::NET, "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; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | #endif | ||||
r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)); | r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)); | ||||
if (r == 1) { | if (r == 1) { | ||||
if (fDiscover) { | if (fDiscover) { | ||||
char externalIPAddress[40]; | char externalIPAddress[40]; | ||||
r = UPNP_GetExternalIPAddress( | r = UPNP_GetExternalIPAddress( | ||||
urls.controlURL, data.first.servicetype, externalIPAddress); | urls.controlURL, data.first.servicetype, externalIPAddress); | ||||
if (r != UPNPCOMMAND_SUCCESS) { | if (r != UPNPCOMMAND_SUCCESS) { | ||||
LogPrintf("UPnP: GetExternalIPAddress() returned %d\n", r); | LogPrint(BCLog::NET, | ||||
"UPnP: GetExternalIPAddress() returned %d\n", r); | |||||
} else { | } else { | ||||
if (externalIPAddress[0]) { | if (externalIPAddress[0]) { | ||||
CNetAddr resolved; | CNetAddr resolved; | ||||
if (LookupHost(externalIPAddress, resolved, false)) { | if (LookupHost(externalIPAddress, resolved, false)) { | ||||
LogPrintf("UPnP: ExternalIPAddress = %s\n", | LogPrint(BCLog::NET, "UPnP: ExternalIPAddress = %s\n", | ||||
resolved.ToString().c_str()); | resolved.ToString().c_str()); | ||||
AddLocal(resolved, LOCAL_UPNP); | AddLocal(resolved, LOCAL_UPNP); | ||||
} | } | ||||
} else { | } else { | ||||
LogPrintf("UPnP: GetExternalIPAddress failed.\n"); | LogPrint(BCLog::NET, | ||||
"UPnP: GetExternalIPAddress failed.\n"); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
std::string strDesc = "Bitcoin " + FormatFullVersion(); | std::string strDesc = "Bitcoin " + FormatFullVersion(); | ||||
do { | do { | ||||
#ifndef UPNPDISCOVER_SUCCESS | #ifndef UPNPDISCOVER_SUCCESS | ||||
/* miniupnpc 1.5 */ | /* miniupnpc 1.5 */ | ||||
r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, | r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, | ||||
port.c_str(), port.c_str(), lanaddr, | port.c_str(), port.c_str(), lanaddr, | ||||
strDesc.c_str(), "TCP", 0); | strDesc.c_str(), "TCP", 0); | ||||
#else | #else | ||||
/* miniupnpc 1.6 */ | /* miniupnpc 1.6 */ | ||||
r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, | r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, | ||||
port.c_str(), port.c_str(), lanaddr, | port.c_str(), port.c_str(), lanaddr, | ||||
strDesc.c_str(), "TCP", 0, "0"); | strDesc.c_str(), "TCP", 0, "0"); | ||||
#endif | #endif | ||||
if (r != UPNPCOMMAND_SUCCESS) { | if (r != UPNPCOMMAND_SUCCESS) { | ||||
LogPrintf( | LogPrint( | ||||
BCLog::NET, | |||||
"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"); | LogPrint(BCLog::NET, "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); | LogPrint(BCLog::NET, "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"); | LogPrint(BCLog::NET, "No valid UPnP IGDs found\n"); | ||||
freeUPNPDevlist(devlist); | freeUPNPDevlist(devlist); | ||||
devlist = nullptr; | devlist = nullptr; | ||||
if (r != 0) { | if (r != 0) { | ||||
FreeUPNPUrls(&urls); | FreeUPNPUrls(&urls); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | if ((addrman.size() > 0) && | ||||
LOCK(cs_vNodes); | LOCK(cs_vNodes); | ||||
int nRelevant = 0; | int nRelevant = 0; | ||||
for (const CNode *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"); | LogPrint(BCLog::NET, "P2P peers available. Skipped DNS seeding.\n"); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
const std::vector<std::string> &vSeeds = | const std::vector<std::string> &vSeeds = | ||||
config->GetChainParams().DNSSeeds(); | config->GetChainParams().DNSSeeds(); | ||||
int found = 0; | int found = 0; | ||||
LogPrintf("Loading addresses from DNS seeds (could take a while)\n"); | LogPrint(BCLog::NET, | ||||
"Loading addresses from DNS seeds (could take a while)\n"); | |||||
for (const std::string &seed : vSeeds) { | for (const std::string &seed : vSeeds) { | ||||
if (interruptNet) { | if (interruptNet) { | ||||
return; | return; | ||||
} | } | ||||
if (HaveNameProxy()) { | if (HaveNameProxy()) { | ||||
AddOneShot(seed); | AddOneShot(seed); | ||||
} else { | } else { | ||||
Show All 25 Lines | for (const std::string &seed : vSeeds) { | ||||
// We now avoid directly using results from DNS Seeds which do | // We now avoid directly using results from DNS Seeds which do | ||||
// not support service bit filtering, instead using them as a | // not support service bit filtering, instead using them as a | ||||
// oneshot to get nodes with our desired service bits. | // oneshot to get nodes with our desired service bits. | ||||
AddOneShot(seed); | AddOneShot(seed); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
LogPrintf("%d addresses found from DNS seeds\n", found); | LogPrint(BCLog::NET, "%d addresses found from DNS seeds\n", found); | ||||
} | } | ||||
void CConnman::DumpAddresses() { | void CConnman::DumpAddresses() { | ||||
int64_t nStart = GetTimeMillis(); | int64_t nStart = GetTimeMillis(); | ||||
CAddrDB adb(config->GetChainParams()); | CAddrDB adb(config->GetChainParams()); | ||||
adb.Write(addrman); | adb.Write(addrman); | ||||
▲ Show 20 Lines • Show All 93 Lines • ▼ Show 20 Lines | while (!interruptNet) { | ||||
if (interruptNet) { | if (interruptNet) { | ||||
return; | return; | ||||
} | } | ||||
// Add seed nodes if DNS seeds are all down (an infrastructure attack?). | // Add seed nodes if DNS seeds are all down (an infrastructure attack?). | ||||
if (addrman.size() == 0 && (GetTime() - nStart > 60)) { | if (addrman.size() == 0 && (GetTime() - nStart > 60)) { | ||||
static bool done = false; | static bool done = false; | ||||
if (!done) { | if (!done) { | ||||
LogPrintf("Adding fixed seed nodes as DNS doesn't seem to be " | LogPrint(BCLog::NET, | ||||
"Adding fixed seed nodes as DNS doesn't seem to be " | |||||
"available.\n"); | "available.\n"); | ||||
CNetAddr local; | CNetAddr local; | ||||
local.SetInternal("fixedseeds"); | local.SetInternal("fixedseeds"); | ||||
addrman.Add(convertSeed6(config->GetChainParams().FixedSeeds()), | addrman.Add(convertSeed6(config->GetChainParams().FixedSeeds()), | ||||
local); | local); | ||||
done = true; | done = true; | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 328 Lines • ▼ Show 20 Lines | bool CConnman::BindListenPort(const CService &addrBind, std::string &strError, | ||||
int nOne = 1; | int nOne = 1; | ||||
// Create socket for listening for incoming connections | // Create socket for listening for incoming connections | ||||
struct sockaddr_storage sockaddr; | struct sockaddr_storage sockaddr; | ||||
socklen_t len = sizeof(sockaddr); | socklen_t len = sizeof(sockaddr); | ||||
if (!addrBind.GetSockAddr((struct sockaddr *)&sockaddr, &len)) { | if (!addrBind.GetSockAddr((struct sockaddr *)&sockaddr, &len)) { | ||||
strError = strprintf("Error: Bind address family for %s not supported", | strError = strprintf("Error: Bind address family for %s not supported", | ||||
addrBind.ToString()); | addrBind.ToString()); | ||||
LogPrintf("%s\n", strError); | LogPrint(BCLog::NET, "%s\n", strError); | ||||
return false; | return false; | ||||
} | } | ||||
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); | LogPrint(BCLog::NET, "%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)); | ||||
Show All 19 Lines | if (::bind(hListenSocket, (struct sockaddr *)&sockaddr, len) == | ||||
strError = strprintf(_("Unable to bind to %s on this computer. %s " | strError = strprintf(_("Unable to bind to %s on this computer. %s " | ||||
"is probably already running."), | "is probably already running."), | ||||
addrBind.ToString(), _(PACKAGE_NAME)); | addrBind.ToString(), _(PACKAGE_NAME)); | ||||
} else { | } else { | ||||
strError = strprintf(_("Unable to bind to %s on this computer " | strError = strprintf(_("Unable to bind to %s on this computer " | ||||
"(bind returned error %s)"), | "(bind returned error %s)"), | ||||
addrBind.ToString(), NetworkErrorString(nErr)); | addrBind.ToString(), NetworkErrorString(nErr)); | ||||
} | } | ||||
LogPrintf("%s\n", strError); | LogPrint(BCLog::NET, "%s\n", strError); | ||||
CloseSocket(hListenSocket); | CloseSocket(hListenSocket); | ||||
return false; | return false; | ||||
} | } | ||||
LogPrintf("Bound to %s\n", addrBind.ToString()); | LogPrint(BCLog::NET, "Bound to %s\n", addrBind.ToString()); | ||||
// Listen for incoming connections | // Listen for incoming connections | ||||
if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR) { | if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR) { | ||||
strError = strprintf(_("Error: Listening for incoming connections " | strError = strprintf(_("Error: Listening for incoming connections " | ||||
"failed (listen returned error %s)"), | "failed (listen returned error %s)"), | ||||
NetworkErrorString(WSAGetLastError())); | NetworkErrorString(WSAGetLastError())); | ||||
LogPrintf("%s\n", strError); | LogPrint(BCLog::NET, "%s\n", strError); | ||||
CloseSocket(hListenSocket); | CloseSocket(hListenSocket); | ||||
return false; | return false; | ||||
} | } | ||||
vhListenSocket.push_back(ListenSocket(hListenSocket, fWhitelisted)); | vhListenSocket.push_back(ListenSocket(hListenSocket, fWhitelisted)); | ||||
if (addrBind.IsRoutable() && fDiscover && !fWhitelisted) { | if (addrBind.IsRoutable() && fDiscover && !fWhitelisted) { | ||||
AddLocal(addrBind, LOCAL_BIND); | AddLocal(addrBind, LOCAL_BIND); | ||||
Show All 10 Lines | |||||
#ifdef WIN32 | #ifdef WIN32 | ||||
// Get local host IP | // Get local host IP | ||||
char pszHostName[256] = ""; | char pszHostName[256] = ""; | ||||
if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR) { | if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR) { | ||||
std::vector<CNetAddr> vaddr; | std::vector<CNetAddr> vaddr; | ||||
if (LookupHost(pszHostName, vaddr, 0, true)) { | if (LookupHost(pszHostName, vaddr, 0, true)) { | ||||
for (const CNetAddr &addr : vaddr) { | for (const CNetAddr &addr : vaddr) { | ||||
if (AddLocal(addr, LOCAL_IF)) { | if (AddLocal(addr, LOCAL_IF)) { | ||||
LogPrintf("%s: %s - %s\n", __func__, pszHostName, | LogPrint(BCLog::NET, "%s: %s - %s\n", __func__, pszHostName, | ||||
addr.ToString()); | addr.ToString()); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
#else | #else | ||||
// Get local host ip | // Get local host ip | ||||
struct ifaddrs *myaddrs; | struct ifaddrs *myaddrs; | ||||
if (getifaddrs(&myaddrs) == 0) { | if (getifaddrs(&myaddrs) == 0) { | ||||
for (struct ifaddrs *ifa = myaddrs; ifa != nullptr; | for (struct ifaddrs *ifa = myaddrs; ifa != nullptr; | ||||
ifa = ifa->ifa_next) { | ifa = ifa->ifa_next) { | ||||
if (ifa->ifa_addr == nullptr || (ifa->ifa_flags & IFF_UP) == 0 || | if (ifa->ifa_addr == nullptr || (ifa->ifa_flags & IFF_UP) == 0 || | ||||
strcmp(ifa->ifa_name, "lo") == 0 || | strcmp(ifa->ifa_name, "lo") == 0 || | ||||
strcmp(ifa->ifa_name, "lo0") == 0) { | strcmp(ifa->ifa_name, "lo0") == 0) { | ||||
continue; | continue; | ||||
} | } | ||||
if (ifa->ifa_addr->sa_family == AF_INET) { | if (ifa->ifa_addr->sa_family == AF_INET) { | ||||
struct sockaddr_in *s4 = (struct sockaddr_in *)(ifa->ifa_addr); | struct sockaddr_in *s4 = (struct sockaddr_in *)(ifa->ifa_addr); | ||||
CNetAddr addr(s4->sin_addr); | CNetAddr addr(s4->sin_addr); | ||||
if (AddLocal(addr, LOCAL_IF)) { | if (AddLocal(addr, LOCAL_IF)) { | ||||
LogPrintf("%s: IPv4 %s: %s\n", __func__, ifa->ifa_name, | LogPrint(BCLog::NET, "%s: IPv4 %s: %s\n", __func__, | ||||
addr.ToString()); | ifa->ifa_name, addr.ToString()); | ||||
} | } | ||||
} else if (ifa->ifa_addr->sa_family == AF_INET6) { | } else if (ifa->ifa_addr->sa_family == AF_INET6) { | ||||
struct sockaddr_in6 *s6 = | struct sockaddr_in6 *s6 = | ||||
(struct sockaddr_in6 *)(ifa->ifa_addr); | (struct sockaddr_in6 *)(ifa->ifa_addr); | ||||
CNetAddr addr(s6->sin6_addr); | CNetAddr addr(s6->sin6_addr); | ||||
if (AddLocal(addr, LOCAL_IF)) { | if (AddLocal(addr, LOCAL_IF)) { | ||||
LogPrintf("%s: IPv6 %s: %s\n", __func__, ifa->ifa_name, | LogPrint(BCLog::NET, "%s: IPv6 %s: %s\n", __func__, | ||||
addr.ToString()); | ifa->ifa_name, addr.ToString()); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
freeifaddrs(myaddrs); | freeifaddrs(myaddrs); | ||||
} | } | ||||
#endif | #endif | ||||
} | } | ||||
▲ Show 20 Lines • Show All 88 Lines • ▼ Show 20 Lines | bool CConnman::Start(CScheduler &scheduler, const Options &connOptions) { | ||||
if (clientInterface) { | if (clientInterface) { | ||||
clientInterface->InitMessage(_("Loading P2P 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", | LogPrint(BCLog::NET, "Loaded %i addresses from peers.dat %dms\n", | ||||
addrman.size(), GetTimeMillis() - nStart); | addrman.size(), GetTimeMillis() - nStart); | ||||
} else { | } else { | ||||
// Addrman can be in an inconsistent state after failure, reset it | // Addrman can be in an inconsistent state after failure, reset it | ||||
addrman.Clear(); | addrman.Clear(); | ||||
LogPrintf("Invalid or missing peers.dat; recreating\n"); | LogPrint(BCLog::NET, "Invalid or missing peers.dat; recreating\n"); | ||||
DumpAddresses(); | DumpAddresses(); | ||||
} | } | ||||
} | } | ||||
if (clientInterface) { | if (clientInterface) { | ||||
clientInterface->InitMessage(_("Loading banlist...")); | clientInterface->InitMessage(_("Loading banlist...")); | ||||
} | } | ||||
// Load addresses from banlist.dat | // Load addresses from banlist.dat | ||||
nStart = GetTimeMillis(); | nStart = GetTimeMillis(); | ||||
CBanDB bandb(config->GetChainParams()); | CBanDB bandb(config->GetChainParams()); | ||||
banmap_t banmap; | banmap_t banmap; | ||||
if (bandb.Read(banmap)) { | if (bandb.Read(banmap)) { | ||||
// thread save setter | // thread save setter | ||||
SetBanned(banmap); | SetBanned(banmap); | ||||
// no need to write down, just read data | // no need to write down, just read data | ||||
SetBannedSetDirty(false); | SetBannedSetDirty(false); | ||||
// sweep out unused entries | // sweep out unused entries | ||||
SweepBanned(); | SweepBanned(); | ||||
LogPrint(BCLog::NET, | LogPrint(BCLog::NET, | ||||
"Loaded %d banned node ips/subnets from banlist.dat %dms\n", | "Loaded %d banned node ips/subnets from banlist.dat %dms\n", | ||||
banmap.size(), GetTimeMillis() - nStart); | banmap.size(), GetTimeMillis() - nStart); | ||||
} else { | } else { | ||||
LogPrintf("Invalid or missing banlist.dat; recreating\n"); | LogPrint(BCLog::NET, "Invalid or missing banlist.dat; recreating\n"); | ||||
// force write | // force write | ||||
SetBannedSetDirty(true); | SetBannedSetDirty(true); | ||||
DumpBanlist(); | DumpBanlist(); | ||||
} | } | ||||
uiInterface.InitMessage(_("Starting network threads...")); | uiInterface.InitMessage(_("Starting network threads...")); | ||||
fAddressesInitialized = true; | fAddressesInitialized = true; | ||||
Show All 22 Lines | bool CConnman::Start(CScheduler &scheduler, const Options &connOptions) { | ||||
} | } | ||||
// Send and receive from sockets, accept connections | // Send and receive from sockets, accept connections | ||||
threadSocketHandler = std::thread( | threadSocketHandler = std::thread( | ||||
&TraceThread<std::function<void()>>, "net", | &TraceThread<std::function<void()>>, "net", | ||||
std::function<void()>(std::bind(&CConnman::ThreadSocketHandler, this))); | std::function<void()>(std::bind(&CConnman::ThreadSocketHandler, this))); | ||||
if (!gArgs.GetBoolArg("-dnsseed", true)) { | if (!gArgs.GetBoolArg("-dnsseed", true)) { | ||||
LogPrintf("DNS seeding disabled\n"); | LogPrint(BCLog::NET, "DNS seeding disabled\n"); | ||||
} else { | } else { | ||||
threadDNSAddressSeed = | threadDNSAddressSeed = | ||||
std::thread(&TraceThread<std::function<void()>>, "dnsseed", | std::thread(&TraceThread<std::function<void()>>, "dnsseed", | ||||
std::function<void()>( | std::function<void()>( | ||||
std::bind(&CConnman::ThreadDNSAddressSeed, this))); | std::bind(&CConnman::ThreadDNSAddressSeed, this))); | ||||
} | } | ||||
// Initiate outbound connections from -addnode | // Initiate outbound connections from -addnode | ||||
▲ Show 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | void CConnman::Stop() { | ||||
// Close sockets | // Close sockets | ||||
for (CNode *pnode : vNodes) { | for (CNode *pnode : vNodes) { | ||||
pnode->CloseSocketDisconnect(); | pnode->CloseSocketDisconnect(); | ||||
} | } | ||||
for (ListenSocket &hListenSocket : vhListenSocket) { | for (ListenSocket &hListenSocket : vhListenSocket) { | ||||
if (hListenSocket.socket != INVALID_SOCKET) { | if (hListenSocket.socket != INVALID_SOCKET) { | ||||
if (!CloseSocket(hListenSocket.socket)) { | if (!CloseSocket(hListenSocket.socket)) { | ||||
LogPrintf("CloseSocket(hListenSocket) failed with error %s\n", | LogPrint(BCLog::NET, | ||||
"CloseSocket(hListenSocket) failed with error %s\n", | |||||
NetworkErrorString(WSAGetLastError())); | NetworkErrorString(WSAGetLastError())); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// clean up some globals (to help leak detection) | // clean up some globals (to help leak detection) | ||||
for (CNode *pnode : vNodes) { | for (CNode *pnode : vNodes) { | ||||
DeleteNode(pnode); | DeleteNode(pnode); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 457 Lines • ▼ Show 20 Lines | std::string userAgent(const Config &config) { | ||||
// format excessive blocksize value | // format excessive blocksize value | ||||
std::string eb = getSubVersionEB(config.GetMaxBlockSize()); | std::string eb = getSubVersionEB(config.GetMaxBlockSize()); | ||||
std::vector<std::string> uacomments; | std::vector<std::string> uacomments; | ||||
uacomments.push_back("EB" + eb); | uacomments.push_back("EB" + eb); | ||||
// sanitize comments per BIP-0014, format user agent and check total size | // sanitize comments per BIP-0014, format user agent and check total size | ||||
for (const std::string &cmt : gArgs.GetArgs("-uacomment")) { | for (const std::string &cmt : gArgs.GetArgs("-uacomment")) { | ||||
if (cmt != SanitizeString(cmt, SAFE_CHARS_UA_COMMENT)) { | if (cmt != SanitizeString(cmt, SAFE_CHARS_UA_COMMENT)) { | ||||
LogPrintf( | LogPrint(BCLog::NET, | ||||
"User Agent comment (%s) contains unsafe characters. " | "User Agent comment (%s) contains unsafe characters. " | ||||
"We are going to use a sanitize version of the comment.\n", | "We are going to use a sanitize version of the comment.\n", | ||||
cmt); | cmt); | ||||
} | } | ||||
uacomments.push_back(cmt); | uacomments.push_back(cmt); | ||||
} | } | ||||
std::string subversion = | std::string subversion = | ||||
FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, uacomments); | FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, uacomments); | ||||
if (subversion.size() > MAX_SUBVERSION_LENGTH) { | if (subversion.size() > MAX_SUBVERSION_LENGTH) { | ||||
LogPrintf("Total length of network version string (%i) exceeds maximum " | LogPrint(BCLog::NET, | ||||
"Total length of network version string (%i) exceeds maximum " | |||||
"length (%i). Reduce the number or size of uacomments. " | "length (%i). Reduce the number or size of uacomments. " | ||||
"String has been resized to the max length allowed.\n", | "String has been resized to the max length allowed.\n", | ||||
subversion.size(), MAX_SUBVERSION_LENGTH); | subversion.size(), MAX_SUBVERSION_LENGTH); | ||||
subversion.resize(MAX_SUBVERSION_LENGTH - 2); | subversion.resize(MAX_SUBVERSION_LENGTH - 2); | ||||
subversion.append(")/"); | subversion.append(")/"); | ||||
LogPrintf("Current network string has been set to: %s\n", subversion); | LogPrint(BCLog::NET, "Current network string has been set to: %s\n", | ||||
subversion); | |||||
} | } | ||||
return subversion; | return subversion; | ||||
} | } |