Changeset View
Changeset View
Standalone View
Standalone View
src/net.cpp
Show First 20 Lines • Show All 407 Lines • ▼ Show 20 Lines | CNode *CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, | ||||
// Connect | // Connect | ||||
bool connected = false; | bool connected = false; | ||||
SOCKET hSocket = INVALID_SOCKET; | SOCKET hSocket = INVALID_SOCKET; | ||||
proxyType proxy; | proxyType proxy; | ||||
if (addrConnect.IsValid()) { | if (addrConnect.IsValid()) { | ||||
bool proxyConnectionFailed = false; | bool proxyConnectionFailed = false; | ||||
if (GetProxy(addrConnect.GetNetwork(), proxy)) { | if (GetProxy(addrConnect.GetNetwork(), proxy)) { | ||||
hSocket = CreateSocket(proxy.proxy); | |||||
if (hSocket == INVALID_SOCKET) { | |||||
return nullptr; | |||||
} | |||||
connected = ConnectThroughProxy( | connected = ConnectThroughProxy( | ||||
proxy, addrConnect.ToStringIP(), addrConnect.GetPort(), hSocket, | proxy, addrConnect.ToStringIP(), addrConnect.GetPort(), hSocket, | ||||
nConnectTimeout, &proxyConnectionFailed); | nConnectTimeout, &proxyConnectionFailed); | ||||
} else { | } else { | ||||
// no proxy needed (none set for target network) | // no proxy needed (none set for target network) | ||||
hSocket = CreateSocket(addrConnect); | |||||
if (hSocket == INVALID_SOCKET) { | |||||
return nullptr; | |||||
} | |||||
connected = | connected = | ||||
ConnectSocketDirectly(addrConnect, hSocket, nConnectTimeout); | ConnectSocketDirectly(addrConnect, hSocket, nConnectTimeout); | ||||
} | } | ||||
if (!proxyConnectionFailed) { | if (!proxyConnectionFailed) { | ||||
// If a connection to the node was attempted, and failure (if any) | // 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 | // is not caused by a problem connecting to the proxy, mark this as | ||||
// an attempt. | // an attempt. | ||||
addrman.Attempt(addrConnect, fCountFailure); | addrman.Attempt(addrConnect, fCountFailure); | ||||
} | } | ||||
} else if (pszDest && GetNameProxy(proxy)) { | } else if (pszDest && GetNameProxy(proxy)) { | ||||
hSocket = CreateSocket(proxy.proxy); | |||||
if (hSocket == INVALID_SOCKET) { | |||||
return nullptr; | |||||
} | |||||
std::string host; | std::string host; | ||||
int port = default_port; | int port = default_port; | ||||
SplitHostPort(std::string(pszDest), port, host); | SplitHostPort(std::string(pszDest), port, host); | ||||
connected = ConnectThroughProxy(proxy, host, port, hSocket, | connected = ConnectThroughProxy(proxy, host, port, hSocket, | ||||
nConnectTimeout, nullptr); | nConnectTimeout, nullptr); | ||||
} | } | ||||
if (connected) { | if (!connected) { | ||||
if (!IsSelectableSocket(hSocket)) { | |||||
LogPrintf("Cannot create connection: non-selectable socket created " | |||||
"(fd >= FD_SETSIZE ?)\n"); | |||||
CloseSocket(hSocket); | CloseSocket(hSocket); | ||||
return nullptr; | 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, | ||||
new CNode(id, nLocalServices, GetBestHeight(), hSocket, addrConnect, | addrConnect, CalculateKeyedNetGroup(addrConnect), | ||||
CalculateKeyedNetGroup(addrConnect), nonce, addr_bind, | nonce, addr_bind, pszDest ? pszDest : "", false); | ||||
pszDest ? pszDest : "", false); | |||||
pnode->AddRef(); | pnode->AddRef(); | ||||
return pnode; | return pnode; | ||||
} | } | ||||
return nullptr; | |||||
} | |||||
void CConnman::DumpBanlist() { | void CConnman::DumpBanlist() { | ||||
// Clean unused entries (if bantime has expired) | // Clean unused entries (if bantime has expired) | ||||
SweepBanned(); | SweepBanned(); | ||||
if (!BannedSetIsDirty()) { | if (!BannedSetIsDirty()) { | ||||
return; | return; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,724 Lines • ▼ Show 20 Lines | bool CConnman::BindListenPort(const CService &addrBind, std::string &strError, | ||||
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); | LogPrintf("%s\n", strError); | ||||
return false; | return false; | ||||
} | } | ||||
SOCKET hListenSocket = socket(((struct sockaddr *)&sockaddr)->sa_family, | SOCKET hListenSocket = CreateSocket(addrBind); | ||||
SOCK_STREAM, IPPROTO_TCP); | |||||
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; | ||||
} | } | ||||
if (!IsSelectableSocket(hListenSocket)) { | |||||
strError = "Error: Couldn't create a listenable socket for incoming " | |||||
"connections"; | |||||
LogPrintf("%s\n", strError); | |||||
return false; | |||||
} | |||||
#ifndef WIN32 | #ifndef WIN32 | ||||
#ifdef SO_NOSIGPIPE | |||||
// Different way of disabling SIGPIPE on BSD | |||||
setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void *)&nOne, | |||||
sizeof(int)); | |||||
#endif | |||||
// 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, (void *)&nOne, | setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void *)&nOne, | ||||
sizeof(int)); | sizeof(int)); | ||||
// Disable Nagle's algorithm | |||||
setsockopt(hListenSocket, IPPROTO_TCP, TCP_NODELAY, (void *)&nOne, | |||||
sizeof(int)); | |||||
#else | #else | ||||
setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (const char *)&nOne, | setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (const char *)&nOne, | ||||
sizeof(int)); | sizeof(int)); | ||||
setsockopt(hListenSocket, IPPROTO_TCP, TCP_NODELAY, (const char *)&nOne, | |||||
sizeof(int)); | |||||
#endif | #endif | ||||
// Set to non-blocking, incoming connections will also inherit this | |||||
if (!SetSocketNonBlocking(hListenSocket, true)) { | |||||
CloseSocket(hListenSocket); | |||||
strError = strprintf("BindListenPort: Setting listening socket to " | |||||
"non-blocking failed, error %s\n", | |||||
NetworkErrorString(WSAGetLastError())); | |||||
LogPrintf("%s\n", strError); | |||||
return false; | |||||
} | |||||
// 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. | ||||
if (addrBind.IsIPv6()) { | if (addrBind.IsIPv6()) { | ||||
#ifdef IPV6_V6ONLY | #ifdef IPV6_V6ONLY | ||||
#ifdef WIN32 | #ifdef WIN32 | ||||
setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, | setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, | ||||
(const char *)&nOne, sizeof(int)); | (const char *)&nOne, sizeof(int)); | ||||
▲ Show 20 Lines • Show All 880 Lines • Show Last 20 Lines |