Changeset View
Changeset View
Standalone View
Standalone View
src/netbase.cpp
Show First 20 Lines • Show All 309 Lines • ▼ Show 20 Lines | switch (err) { | ||||
return "address type not supported"; | return "address type not supported"; | ||||
default: | default: | ||||
return "unknown"; | return "unknown"; | ||||
} | } | ||||
} | } | ||||
/** Connect using SOCKS5 (as described in RFC1928) */ | /** Connect using SOCKS5 (as described in RFC1928) */ | ||||
static bool Socks5(const std::string &strDest, int port, | static bool Socks5(const std::string &strDest, int port, | ||||
const ProxyCredentials *auth, SOCKET &hSocket) { | const ProxyCredentials *auth, const SOCKET &hSocket) { | ||||
IntrRecvError recvr; | IntrRecvError recvr; | ||||
LogPrint(BCLog::NET, "SOCKS5 connecting %s\n", strDest); | LogPrint(BCLog::NET, "SOCKS5 connecting %s\n", strDest); | ||||
if (strDest.size() > 255) { | if (strDest.size() > 255) { | ||||
CloseSocket(hSocket); | |||||
return error("Hostname too long"); | return error("Hostname too long"); | ||||
} | } | ||||
// Accepted authentication methods | // Accepted authentication methods | ||||
std::vector<uint8_t> vSocks5Init; | std::vector<uint8_t> vSocks5Init; | ||||
vSocks5Init.push_back(SOCKSVersion::SOCKS5); | vSocks5Init.push_back(SOCKSVersion::SOCKS5); | ||||
if (auth) { | if (auth) { | ||||
vSocks5Init.push_back(0x02); // Number of methods | vSocks5Init.push_back(0x02); // Number of methods | ||||
vSocks5Init.push_back(SOCKS5Method::NOAUTH); | vSocks5Init.push_back(SOCKS5Method::NOAUTH); | ||||
vSocks5Init.push_back(SOCKS5Method::USER_PASS); | vSocks5Init.push_back(SOCKS5Method::USER_PASS); | ||||
} else { | } else { | ||||
vSocks5Init.push_back(0x01); // Number of methods | vSocks5Init.push_back(0x01); // Number of methods | ||||
vSocks5Init.push_back(SOCKS5Method::NOAUTH); | vSocks5Init.push_back(SOCKS5Method::NOAUTH); | ||||
} | } | ||||
ssize_t ret = send(hSocket, (const char *)vSocks5Init.data(), | ssize_t ret = send(hSocket, (const char *)vSocks5Init.data(), | ||||
vSocks5Init.size(), MSG_NOSIGNAL); | vSocks5Init.size(), MSG_NOSIGNAL); | ||||
if (ret != (ssize_t)vSocks5Init.size()) { | if (ret != (ssize_t)vSocks5Init.size()) { | ||||
CloseSocket(hSocket); | |||||
return error("Error sending to proxy"); | return error("Error sending to proxy"); | ||||
} | } | ||||
uint8_t pchRet1[2]; | uint8_t pchRet1[2]; | ||||
if ((recvr = InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != | if ((recvr = InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != | ||||
IntrRecvError::OK) { | IntrRecvError::OK) { | ||||
CloseSocket(hSocket); | |||||
LogPrintf("Socks5() connect to %s:%d failed: InterruptibleRecv() " | LogPrintf("Socks5() connect to %s:%d failed: InterruptibleRecv() " | ||||
"timeout or other failure\n", | "timeout or other failure\n", | ||||
strDest, port); | strDest, port); | ||||
return false; | return false; | ||||
} | } | ||||
if (pchRet1[0] != SOCKSVersion::SOCKS5) { | if (pchRet1[0] != SOCKSVersion::SOCKS5) { | ||||
CloseSocket(hSocket); | |||||
return error("Proxy failed to initialize"); | return error("Proxy failed to initialize"); | ||||
} | } | ||||
if (pchRet1[1] == SOCKS5Method::USER_PASS && auth) { | if (pchRet1[1] == SOCKS5Method::USER_PASS && auth) { | ||||
// Perform username/password authentication (as described in RFC1929) | // Perform username/password authentication (as described in RFC1929) | ||||
std::vector<uint8_t> vAuth; | std::vector<uint8_t> vAuth; | ||||
// Current (and only) version of user/pass subnegotiation | // Current (and only) version of user/pass subnegotiation | ||||
vAuth.push_back(0x01); | vAuth.push_back(0x01); | ||||
if (auth->username.size() > 255 || auth->password.size() > 255) | if (auth->username.size() > 255 || auth->password.size() > 255) | ||||
return error("Proxy username or password too long"); | return error("Proxy username or password too long"); | ||||
vAuth.push_back(auth->username.size()); | vAuth.push_back(auth->username.size()); | ||||
vAuth.insert(vAuth.end(), auth->username.begin(), auth->username.end()); | vAuth.insert(vAuth.end(), auth->username.begin(), auth->username.end()); | ||||
vAuth.push_back(auth->password.size()); | vAuth.push_back(auth->password.size()); | ||||
vAuth.insert(vAuth.end(), auth->password.begin(), auth->password.end()); | vAuth.insert(vAuth.end(), auth->password.begin(), auth->password.end()); | ||||
ret = send(hSocket, (const char *)vAuth.data(), vAuth.size(), | ret = send(hSocket, (const char *)vAuth.data(), vAuth.size(), | ||||
MSG_NOSIGNAL); | MSG_NOSIGNAL); | ||||
if (ret != (ssize_t)vAuth.size()) { | if (ret != (ssize_t)vAuth.size()) { | ||||
CloseSocket(hSocket); | |||||
return error("Error sending authentication to proxy"); | return error("Error sending authentication to proxy"); | ||||
} | } | ||||
LogPrint(BCLog::PROXY, "SOCKS5 sending proxy authentication %s:%s\n", | LogPrint(BCLog::PROXY, "SOCKS5 sending proxy authentication %s:%s\n", | ||||
auth->username, auth->password); | auth->username, auth->password); | ||||
uint8_t pchRetA[2]; | uint8_t pchRetA[2]; | ||||
if ((recvr = InterruptibleRecv(pchRetA, 2, SOCKS5_RECV_TIMEOUT, | if ((recvr = InterruptibleRecv(pchRetA, 2, SOCKS5_RECV_TIMEOUT, | ||||
hSocket)) != IntrRecvError::OK) { | hSocket)) != IntrRecvError::OK) { | ||||
CloseSocket(hSocket); | |||||
return error("Error reading proxy authentication response"); | return error("Error reading proxy authentication response"); | ||||
} | } | ||||
if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) { | if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) { | ||||
CloseSocket(hSocket); | |||||
return error("Proxy authentication unsuccessful"); | return error("Proxy authentication unsuccessful"); | ||||
} | } | ||||
} else if (pchRet1[1] == SOCKS5Method::NOAUTH) { | } else if (pchRet1[1] == SOCKS5Method::NOAUTH) { | ||||
// Perform no authentication | // Perform no authentication | ||||
} else { | } else { | ||||
CloseSocket(hSocket); | |||||
return error("Proxy requested wrong authentication method %02x", | return error("Proxy requested wrong authentication method %02x", | ||||
pchRet1[1]); | pchRet1[1]); | ||||
} | } | ||||
std::vector<uint8_t> vSocks5; | std::vector<uint8_t> vSocks5; | ||||
// VER protocol version | // VER protocol version | ||||
vSocks5.push_back(SOCKSVersion::SOCKS5); | vSocks5.push_back(SOCKSVersion::SOCKS5); | ||||
// CMD CONNECT | // CMD CONNECT | ||||
vSocks5.push_back(SOCKS5Command::CONNECT); | vSocks5.push_back(SOCKS5Command::CONNECT); | ||||
// RSV Reserved must be 0 | // RSV Reserved must be 0 | ||||
vSocks5.push_back(0x00); | vSocks5.push_back(0x00); | ||||
// ATYP DOMAINNAME | // ATYP DOMAINNAME | ||||
vSocks5.push_back(SOCKS5Atyp::DOMAINNAME); | vSocks5.push_back(SOCKS5Atyp::DOMAINNAME); | ||||
// Length<=255 is checked at beginning of function | // Length<=255 is checked at beginning of function | ||||
vSocks5.push_back(strDest.size()); | vSocks5.push_back(strDest.size()); | ||||
vSocks5.insert(vSocks5.end(), strDest.begin(), strDest.end()); | vSocks5.insert(vSocks5.end(), strDest.begin(), strDest.end()); | ||||
vSocks5.push_back((port >> 8) & 0xFF); | vSocks5.push_back((port >> 8) & 0xFF); | ||||
vSocks5.push_back((port >> 0) & 0xFF); | vSocks5.push_back((port >> 0) & 0xFF); | ||||
ret = send(hSocket, (const char *)vSocks5.data(), vSocks5.size(), | ret = send(hSocket, (const char *)vSocks5.data(), vSocks5.size(), | ||||
MSG_NOSIGNAL); | MSG_NOSIGNAL); | ||||
if (ret != (ssize_t)vSocks5.size()) { | if (ret != (ssize_t)vSocks5.size()) { | ||||
CloseSocket(hSocket); | |||||
return error("Error sending to proxy"); | return error("Error sending to proxy"); | ||||
} | } | ||||
uint8_t pchRet2[4]; | uint8_t pchRet2[4]; | ||||
if ((recvr = InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, hSocket)) != | if ((recvr = InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, hSocket)) != | ||||
IntrRecvError::OK) { | IntrRecvError::OK) { | ||||
CloseSocket(hSocket); | |||||
if (recvr == IntrRecvError::Timeout) { | if (recvr == IntrRecvError::Timeout) { | ||||
/** | /** | ||||
* If a timeout happens here, this effectively means we timed out | * If a timeout happens here, this effectively means we timed out | ||||
* while connecting to the remote node. This is very common for Tor, | * while connecting to the remote node. This is very common for Tor, | ||||
* so do not print an error message. | * so do not print an error message. | ||||
*/ | */ | ||||
return false; | return false; | ||||
} else { | } else { | ||||
return error("Error while reading proxy response"); | return error("Error while reading proxy response"); | ||||
} | } | ||||
} | } | ||||
if (pchRet2[0] != SOCKSVersion::SOCKS5) { | if (pchRet2[0] != SOCKSVersion::SOCKS5) { | ||||
CloseSocket(hSocket); | |||||
return error("Proxy failed to accept request"); | return error("Proxy failed to accept request"); | ||||
} | } | ||||
if (pchRet2[1] != SOCKS5Reply::SUCCEEDED) { | if (pchRet2[1] != SOCKS5Reply::SUCCEEDED) { | ||||
// Failures to connect to a peer that are not proxy errors | // Failures to connect to a peer that are not proxy errors | ||||
CloseSocket(hSocket); | |||||
LogPrintf("Socks5() connect to %s:%d failed: %s\n", strDest, port, | LogPrintf("Socks5() connect to %s:%d failed: %s\n", strDest, port, | ||||
Socks5ErrorString(pchRet2[1])); | Socks5ErrorString(pchRet2[1])); | ||||
return false; | return false; | ||||
} | } | ||||
// Reserved field must be 0 | // Reserved field must be 0 | ||||
if (pchRet2[2] != 0x00) { | if (pchRet2[2] != 0x00) { | ||||
CloseSocket(hSocket); | |||||
return error("Error: malformed proxy response"); | return error("Error: malformed proxy response"); | ||||
} | } | ||||
uint8_t pchRet3[256]; | uint8_t pchRet3[256]; | ||||
switch (pchRet2[3]) { | switch (pchRet2[3]) { | ||||
case SOCKS5Atyp::IPV4: | case SOCKS5Atyp::IPV4: | ||||
recvr = InterruptibleRecv(pchRet3, 4, SOCKS5_RECV_TIMEOUT, hSocket); | recvr = InterruptibleRecv(pchRet3, 4, SOCKS5_RECV_TIMEOUT, hSocket); | ||||
break; | break; | ||||
case SOCKS5Atyp::IPV6: | case SOCKS5Atyp::IPV6: | ||||
recvr = | recvr = | ||||
InterruptibleRecv(pchRet3, 16, SOCKS5_RECV_TIMEOUT, hSocket); | InterruptibleRecv(pchRet3, 16, SOCKS5_RECV_TIMEOUT, hSocket); | ||||
break; | break; | ||||
case SOCKS5Atyp::DOMAINNAME: { | case SOCKS5Atyp::DOMAINNAME: { | ||||
recvr = InterruptibleRecv(pchRet3, 1, SOCKS5_RECV_TIMEOUT, hSocket); | recvr = InterruptibleRecv(pchRet3, 1, SOCKS5_RECV_TIMEOUT, hSocket); | ||||
if (recvr != IntrRecvError::OK) { | if (recvr != IntrRecvError::OK) { | ||||
CloseSocket(hSocket); | |||||
return error("Error reading from proxy"); | return error("Error reading from proxy"); | ||||
} | } | ||||
int nRecv = pchRet3[0]; | int nRecv = pchRet3[0]; | ||||
recvr = | recvr = | ||||
InterruptibleRecv(pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, hSocket); | InterruptibleRecv(pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, hSocket); | ||||
break; | break; | ||||
} | } | ||||
default: | default: | ||||
CloseSocket(hSocket); | |||||
return error("Error: malformed proxy response"); | return error("Error: malformed proxy response"); | ||||
} | } | ||||
if (recvr != IntrRecvError::OK) { | if (recvr != IntrRecvError::OK) { | ||||
CloseSocket(hSocket); | |||||
return error("Error reading from proxy"); | return error("Error reading from proxy"); | ||||
} | } | ||||
if ((recvr = InterruptibleRecv(pchRet3, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != | if ((recvr = InterruptibleRecv(pchRet3, 2, SOCKS5_RECV_TIMEOUT, hSocket)) != | ||||
IntrRecvError::OK) { | IntrRecvError::OK) { | ||||
CloseSocket(hSocket); | |||||
return error("Error reading from proxy"); | return error("Error reading from proxy"); | ||||
} | } | ||||
LogPrint(BCLog::NET, "SOCKS5 connected %s\n", strDest); | LogPrint(BCLog::NET, "SOCKS5 connected %s\n", strDest); | ||||
return true; | return true; | ||||
} | } | ||||
bool ConnectSocketDirectly(const CService &addrConnect, SOCKET &hSocketRet, | SOCKET CreateSocket(const CService &addrConnect) { | ||||
int nTimeout) { | |||||
hSocketRet = INVALID_SOCKET; | |||||
struct sockaddr_storage sockaddr; | struct sockaddr_storage sockaddr; | ||||
socklen_t len = sizeof(sockaddr); | socklen_t len = sizeof(sockaddr); | ||||
if (!addrConnect.GetSockAddr((struct sockaddr *)&sockaddr, &len)) { | if (!addrConnect.GetSockAddr((struct sockaddr *)&sockaddr, &len)) { | ||||
LogPrintf("Cannot connect to %s: unsupported network\n", | LogPrintf("Cannot create socket for %s: unsupported network\n", | ||||
addrConnect.ToString()); | addrConnect.ToString()); | ||||
return false; | return INVALID_SOCKET; | ||||
} | } | ||||
SOCKET hSocket = socket(((struct sockaddr *)&sockaddr)->sa_family, | SOCKET hSocket = socket(((struct sockaddr *)&sockaddr)->sa_family, | ||||
SOCK_STREAM, IPPROTO_TCP); | SOCK_STREAM, IPPROTO_TCP); | ||||
if (hSocket == INVALID_SOCKET) return false; | if (hSocket == INVALID_SOCKET) { | ||||
return INVALID_SOCKET; | |||||
} | |||||
if (!IsSelectableSocket(hSocket)) { | |||||
CloseSocket(hSocket); | |||||
LogPrintf("Cannot create connection: non-selectable socket created (fd " | |||||
">= FD_SETSIZE ?)\n"); | |||||
return INVALID_SOCKET; | |||||
} | |||||
#ifdef SO_NOSIGPIPE | #ifdef SO_NOSIGPIPE | ||||
int set = 1; | int set = 1; | ||||
// Different way of disabling SIGPIPE on BSD | // Different way of disabling SIGPIPE on BSD | ||||
setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int)); | setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int)); | ||||
#endif | #endif | ||||
// Disable Nagle's algorithm | // Disable Nagle's algorithm | ||||
SetSocketNoDelay(hSocket); | SetSocketNoDelay(hSocket); | ||||
// Set to non-blocking | // Set to non-blocking | ||||
if (!SetSocketNonBlocking(hSocket, true)) { | if (!SetSocketNonBlocking(hSocket, true)) { | ||||
CloseSocket(hSocket); | CloseSocket(hSocket); | ||||
return error("ConnectSocketDirectly: Setting socket to non-blocking " | LogPrintf("ConnectSocketDirectly: Setting socket to non-blocking " | ||||
"failed, error %s\n", | "failed, error %s\n", | ||||
NetworkErrorString(WSAGetLastError())); | NetworkErrorString(WSAGetLastError())); | ||||
} | } | ||||
return hSocket; | |||||
} | |||||
bool ConnectSocketDirectly(const CService &addrConnect, const SOCKET &hSocket, | |||||
int nTimeout) { | |||||
struct sockaddr_storage sockaddr; | |||||
socklen_t len = sizeof(sockaddr); | |||||
if (hSocket == INVALID_SOCKET) { | |||||
LogPrintf("Cannot connect to %s: invalid socket\n", | |||||
addrConnect.ToString()); | |||||
return false; | |||||
} | |||||
if (!addrConnect.GetSockAddr((struct sockaddr *)&sockaddr, &len)) { | |||||
LogPrintf("Cannot connect to %s: unsupported network\n", | |||||
addrConnect.ToString()); | |||||
return false; | |||||
} | |||||
if (connect(hSocket, (struct sockaddr *)&sockaddr, len) == SOCKET_ERROR) { | if (connect(hSocket, (struct sockaddr *)&sockaddr, len) == SOCKET_ERROR) { | ||||
int nErr = WSAGetLastError(); | int nErr = WSAGetLastError(); | ||||
// WSAEINVAL is here because some legacy version of winsock uses it | // WSAEINVAL is here because some legacy version of winsock uses it | ||||
if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || | if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || | ||||
nErr == WSAEINVAL) { | nErr == WSAEINVAL) { | ||||
struct timeval timeout = MillisToTimeval(nTimeout); | struct timeval timeout = MillisToTimeval(nTimeout); | ||||
fd_set fdset; | fd_set fdset; | ||||
FD_ZERO(&fdset); | FD_ZERO(&fdset); | ||||
FD_SET(hSocket, &fdset); | FD_SET(hSocket, &fdset); | ||||
int nRet = select(hSocket + 1, nullptr, &fdset, nullptr, &timeout); | int nRet = select(hSocket + 1, nullptr, &fdset, nullptr, &timeout); | ||||
if (nRet == 0) { | if (nRet == 0) { | ||||
LogPrint(BCLog::NET, "connection to %s timeout\n", | LogPrint(BCLog::NET, "connection to %s timeout\n", | ||||
addrConnect.ToString()); | addrConnect.ToString()); | ||||
CloseSocket(hSocket); | |||||
return false; | return false; | ||||
} | } | ||||
if (nRet == SOCKET_ERROR) { | if (nRet == SOCKET_ERROR) { | ||||
LogPrintf("select() for %s failed: %s\n", | LogPrintf("select() for %s failed: %s\n", | ||||
addrConnect.ToString(), | addrConnect.ToString(), | ||||
NetworkErrorString(WSAGetLastError())); | NetworkErrorString(WSAGetLastError())); | ||||
CloseSocket(hSocket); | |||||
return false; | return false; | ||||
} | } | ||||
socklen_t nRetSize = sizeof(nRet); | socklen_t nRetSize = sizeof(nRet); | ||||
#ifdef WIN32 | #ifdef WIN32 | ||||
if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (char *)(&nRet), | if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (char *)(&nRet), | ||||
&nRetSize) == SOCKET_ERROR) | &nRetSize) == SOCKET_ERROR) | ||||
#else | #else | ||||
if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == | if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == | ||||
SOCKET_ERROR) | SOCKET_ERROR) | ||||
#endif | #endif | ||||
{ | { | ||||
LogPrintf("getsockopt() for %s failed: %s\n", | LogPrintf("getsockopt() for %s failed: %s\n", | ||||
addrConnect.ToString(), | addrConnect.ToString(), | ||||
NetworkErrorString(WSAGetLastError())); | NetworkErrorString(WSAGetLastError())); | ||||
CloseSocket(hSocket); | |||||
return false; | return false; | ||||
} | } | ||||
if (nRet != 0) { | if (nRet != 0) { | ||||
LogPrintf("connect() to %s failed after select(): %s\n", | LogPrintf("connect() to %s failed after select(): %s\n", | ||||
addrConnect.ToString(), NetworkErrorString(nRet)); | addrConnect.ToString(), NetworkErrorString(nRet)); | ||||
CloseSocket(hSocket); | |||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
#ifdef WIN32 | #ifdef WIN32 | ||||
else if (WSAGetLastError() != WSAEISCONN) | else if (WSAGetLastError() != WSAEISCONN) | ||||
#else | #else | ||||
else | else | ||||
#endif | #endif | ||||
{ | { | ||||
LogPrintf("connect() to %s failed: %s\n", addrConnect.ToString(), | LogPrintf("connect() to %s failed: %s\n", addrConnect.ToString(), | ||||
NetworkErrorString(WSAGetLastError())); | NetworkErrorString(WSAGetLastError())); | ||||
CloseSocket(hSocket); | |||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
hSocketRet = hSocket; | |||||
return true; | return true; | ||||
} | } | ||||
bool SetProxy(enum Network net, const proxyType &addrProxy) { | bool SetProxy(enum Network net, const proxyType &addrProxy) { | ||||
assert(net >= 0 && net < NET_MAX); | assert(net >= 0 && net < NET_MAX); | ||||
if (!addrProxy.IsValid()) return false; | if (!addrProxy.IsValid()) return false; | ||||
LOCK(cs_proxyInfos); | LOCK(cs_proxyInfos); | ||||
proxyInfo[net] = addrProxy; | proxyInfo[net] = addrProxy; | ||||
Show All 31 Lines | bool IsProxy(const CNetAddr &addr) { | ||||
LOCK(cs_proxyInfos); | LOCK(cs_proxyInfos); | ||||
for (int i = 0; i < NET_MAX; i++) { | for (int i = 0; i < NET_MAX; i++) { | ||||
if (addr == (CNetAddr)proxyInfo[i].proxy) return true; | if (addr == (CNetAddr)proxyInfo[i].proxy) return true; | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
bool ConnectThroughProxy(const proxyType &proxy, const std::string &strDest, | bool ConnectThroughProxy(const proxyType &proxy, const std::string &strDest, | ||||
int port, SOCKET &hSocketRet, int nTimeout, | int port, const SOCKET &hSocket, int nTimeout, | ||||
bool *outProxyConnectionFailed) { | bool *outProxyConnectionFailed) { | ||||
SOCKET hSocket = INVALID_SOCKET; | |||||
// first connect to proxy server | // first connect to proxy server | ||||
if (!ConnectSocketDirectly(proxy.proxy, hSocket, nTimeout)) { | if (!ConnectSocketDirectly(proxy.proxy, hSocket, nTimeout)) { | ||||
if (outProxyConnectionFailed) *outProxyConnectionFailed = true; | if (outProxyConnectionFailed) *outProxyConnectionFailed = true; | ||||
return false; | return false; | ||||
} | } | ||||
// do socks negotiation | // do socks negotiation | ||||
if (proxy.randomize_credentials) { | if (proxy.randomize_credentials) { | ||||
ProxyCredentials random_auth; | ProxyCredentials random_auth; | ||||
static std::atomic_int counter; | static std::atomic_int counter(0); | ||||
random_auth.username = random_auth.password = | random_auth.username = random_auth.password = | ||||
strprintf("%i", counter++); | strprintf("%i", counter++); | ||||
if (!Socks5(strDest, (unsigned short)port, &random_auth, hSocket)) { | if (!Socks5(strDest, (unsigned short)port, &random_auth, hSocket)) { | ||||
return false; | return false; | ||||
} | } | ||||
} else if (!Socks5(strDest, (unsigned short)port, 0, hSocket)) { | } else if (!Socks5(strDest, (unsigned short)port, 0, hSocket)) { | ||||
return false; | return false; | ||||
} | } | ||||
hSocketRet = hSocket; | |||||
return true; | return true; | ||||
} | } | ||||
bool LookupSubNet(const char *pszName, CSubNet &ret) { | bool LookupSubNet(const char *pszName, CSubNet &ret) { | ||||
std::string strSubnet(pszName); | std::string strSubnet(pszName); | ||||
size_t slash = strSubnet.find_last_of('/'); | size_t slash = strSubnet.find_last_of('/'); | ||||
std::vector<CNetAddr> vIP; | std::vector<CNetAddr> vIP; | ||||
std::string strAddress = strSubnet.substr(0, slash); | std::string strAddress = strSubnet.substr(0, slash); | ||||
▲ Show 20 Lines • Show All 106 Lines • Show Last 20 Lines |