Changeset View
Changeset View
Standalone View
Standalone View
src/net.cpp
Show First 20 Lines • Show All 367 Lines • ▼ Show 20 Lines | CNode *CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, | ||||
/// 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 | ||||
? 0.0 | ? 0.0 | ||||
: (double)(GetAdjustedTime() - addrConnect.nTime) / 3600.0); | : (double)(GetAdjustedTime() - addrConnect.nTime) / 3600.0); | ||||
// Connect | // Resolve | ||||
SOCKET hSocket; | const int default_port = Params().GetDefaultPort(); | ||||
bool proxyConnectionFailed = false; | if (pszDest) { | ||||
if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, | std::vector<CService> resolved; | ||||
config->GetChainParams().GetDefaultPort(), | if (Lookup(pszDest, resolved, default_port, | ||||
nConnectTimeout, &proxyConnectionFailed) | fNameLookup && !HaveNameProxy(), 256) && | ||||
: ConnectSocket(addrConnect, hSocket, nConnectTimeout, | !resolved.empty()) { | ||||
&proxyConnectionFailed)) { | addrConnect = | ||||
if (!IsSelectableSocket(hSocket)) { | CAddress(resolved[GetRand(resolved.size())], NODE_NONE); | ||||
LogPrintf("Cannot create connection: non-selectable socket created " | if (!addrConnect.IsValid()) { | ||||
"(fd >= FD_SETSIZE ?)\n"); | LogPrint(BCLog::NET, | ||||
CloseSocket(hSocket); | "Resolver returned invalid address %s for %s\n", | ||||
addrConnect.ToString(), pszDest); | |||||
return nullptr; | return nullptr; | ||||
} | } | ||||
if (pszDest && addrConnect.IsValid()) { | |||||
// It is possible that we already have a connection to the IP/port | // It is possible that we already have a connection to the IP/port | ||||
// 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((CService)addrConnect); | CNode *pnode = FindNode(static_cast<CService>(addrConnect)); | ||||
if (pnode) { | if (pnode) { | ||||
pnode->MaybeSetAddrName(std::string(pszDest)); | pnode->MaybeSetAddrName(std::string(pszDest)); | ||||
CloseSocket(hSocket); | |||||
LogPrintf("Failed to open new connection, already connected\n"); | LogPrintf("Failed to open new connection, already connected\n"); | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
} | } | ||||
} | |||||
// Connect | |||||
bool connected = false; | |||||
SOCKET hSocket = INVALID_SOCKET; | |||||
proxyType proxy; | |||||
if (addrConnect.IsValid()) { | |||||
bool proxyConnectionFailed = false; | |||||
if (GetProxy(addrConnect.GetNetwork(), proxy)) { | |||||
connected = ConnectThroughProxy( | |||||
proxy, addrConnect.ToStringIP(), addrConnect.GetPort(), hSocket, | |||||
nConnectTimeout, &proxyConnectionFailed); | |||||
} else { | |||||
// no proxy needed (none set for target network) | |||||
connected = | |||||
ConnectSocketDirectly(addrConnect, hSocket, nConnectTimeout); | |||||
} | |||||
if (!proxyConnectionFailed) { | |||||
// If a connection to the node was attempted, and failure (if any) | |||||
// is not caused by a problem connecting to the proxy, mark this as | |||||
// an attempt. | |||||
addrman.Attempt(addrConnect, fCountFailure); | addrman.Attempt(addrConnect, fCountFailure); | ||||
} | |||||
} else if (pszDest && GetNameProxy(proxy)) { | |||||
std::string host; | |||||
int port = default_port; | |||||
SplitHostPort(std::string(pszDest), port, host); | |||||
connected = ConnectThroughProxy(proxy, host, port, hSocket, | |||||
nConnectTimeout, nullptr); | |||||
} | |||||
if (connected) { | |||||
if (!IsSelectableSocket(hSocket)) { | |||||
LogPrintf("Cannot create connection: non-selectable socket created " | |||||
"(fd >= FD_SETSIZE ?)\n"); | |||||
CloseSocket(hSocket); | |||||
return nullptr; | |||||
} | |||||
// Add node | // Add node | ||||
NodeId id = GetNewNodeId(); | NodeId id = GetNewNodeId(); | ||||
uint64_t nonce = | uint64_t nonce = | ||||
GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE) | GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE) | ||||
.Write(id) | .Write(id) | ||||
.Finalize(); | .Finalize(); | ||||
CAddress addr_bind = GetBindAddress(hSocket); | CAddress addr_bind = GetBindAddress(hSocket); | ||||
CNode *pnode = | CNode *pnode = | ||||
new CNode(id, nLocalServices, GetBestHeight(), hSocket, addrConnect, | new CNode(id, nLocalServices, GetBestHeight(), hSocket, addrConnect, | ||||
CalculateKeyedNetGroup(addrConnect), nonce, addr_bind, | CalculateKeyedNetGroup(addrConnect), nonce, addr_bind, | ||||
pszDest ? pszDest : "", false); | pszDest ? pszDest : "", false); | ||||
pnode->AddRef(); | pnode->AddRef(); | ||||
return pnode; | return pnode; | ||||
} else if (!proxyConnectionFailed) { | |||||
// If connecting to the node failed, and failure is not caused by a | |||||
// problem connecting to the proxy, mark this as an attempt. | |||||
addrman.Attempt(addrConnect, fCountFailure); | |||||
} | } | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
void CConnman::DumpBanlist() { | void CConnman::DumpBanlist() { | ||||
// Clean unused entries (if bantime has expired) | // Clean unused entries (if bantime has expired) | ||||
SweepBanned(); | SweepBanned(); | ||||
▲ Show 20 Lines • Show All 1,621 Lines • ▼ Show 20 Lines | while (true) { | ||||
for (const AddedNodeInfo &info : vInfo) { | for (const AddedNodeInfo &info : vInfo) { | ||||
if (!info.fConnected) { | if (!info.fConnected) { | ||||
if (!grant.TryAcquire()) { | if (!grant.TryAcquire()) { | ||||
// If we've used up our semaphore and need a new one, lets | // If we've used up our semaphore and need a new one, lets | ||||
// not wait here since while we are waiting the | // not wait here since while we are waiting the | ||||
// addednodeinfo state might change. | // addednodeinfo state might change. | ||||
break; | break; | ||||
} | } | ||||
// If strAddedNode is an IP/port, decode it immediately, so | |||||
// OpenNetworkConnection can detect existing connections to that | |||||
// IP/port. | |||||
tried = true; | tried = true; | ||||
CService service( | CAddress addr(CService(), NODE_NONE); | ||||
LookupNumeric(info.strAddedNode.c_str(), | OpenNetworkConnection(addr, false, &grant, | ||||
config->GetChainParams().GetDefaultPort())); | info.strAddedNode.c_str(), false, false, | ||||
OpenNetworkConnection(CAddress(service, NODE_NONE), false, | true); | ||||
&grant, info.strAddedNode.c_str(), false, | |||||
false, true); | |||||
if (!interruptNet.sleep_for(std::chrono::milliseconds(500))) { | if (!interruptNet.sleep_for(std::chrono::milliseconds(500))) { | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// Retry every 60 seconds if a connection was attempted, otherwise two | // Retry every 60 seconds if a connection was attempted, otherwise two | ||||
// seconds. | // seconds. | ||||
if (!interruptNet.sleep_for(std::chrono::seconds(tried ? 60 : 2))) { | if (!interruptNet.sleep_for(std::chrono::seconds(tried ? 60 : 2))) { | ||||
▲ Show 20 Lines • Show All 1,066 Lines • Show Last 20 Lines |