|
|
@ -37,7 +37,7 @@ using namespace std; |
|
|
|
|
|
|
|
|
|
|
|
// Settings
|
|
|
|
// Settings
|
|
|
|
static proxyType proxyInfo[NET_MAX]; |
|
|
|
static proxyType proxyInfo[NET_MAX]; |
|
|
|
static proxyType nameproxyInfo; |
|
|
|
static CService nameProxy; |
|
|
|
static CCriticalSection cs_proxyInfos; |
|
|
|
static CCriticalSection cs_proxyInfos; |
|
|
|
int nConnectTimeout = 5000; |
|
|
|
int nConnectTimeout = 5000; |
|
|
|
bool fNameLookup = false; |
|
|
|
bool fNameLookup = false; |
|
|
@ -214,50 +214,6 @@ bool LookupNumeric(const char *pszName, CService& addr, int portDefault) |
|
|
|
return Lookup(pszName, addr, portDefault, false); |
|
|
|
return Lookup(pszName, addr, portDefault, false); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool static Socks4(const CService &addrDest, SOCKET& hSocket) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
LogPrintf("SOCKS4 connecting %s\n", addrDest.ToString()); |
|
|
|
|
|
|
|
if (!addrDest.IsIPv4()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
closesocket(hSocket); |
|
|
|
|
|
|
|
return error("Proxy destination is not IPv4"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user"; |
|
|
|
|
|
|
|
struct sockaddr_in addr; |
|
|
|
|
|
|
|
socklen_t len = sizeof(addr); |
|
|
|
|
|
|
|
if (!addrDest.GetSockAddr((struct sockaddr*)&addr, &len) || addr.sin_family != AF_INET) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
closesocket(hSocket); |
|
|
|
|
|
|
|
return error("Cannot get proxy destination address"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
memcpy(pszSocks4IP + 2, &addr.sin_port, 2); |
|
|
|
|
|
|
|
memcpy(pszSocks4IP + 4, &addr.sin_addr, 4); |
|
|
|
|
|
|
|
char* pszSocks4 = pszSocks4IP; |
|
|
|
|
|
|
|
int nSize = sizeof(pszSocks4IP); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL); |
|
|
|
|
|
|
|
if (ret != nSize) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
closesocket(hSocket); |
|
|
|
|
|
|
|
return error("Error sending to proxy"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
char pchRet[8]; |
|
|
|
|
|
|
|
if (recv(hSocket, pchRet, 8, 0) != 8) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
closesocket(hSocket); |
|
|
|
|
|
|
|
return error("Error reading proxy response"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (pchRet[1] != 0x5a) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
closesocket(hSocket); |
|
|
|
|
|
|
|
if (pchRet[1] != 0x5b) |
|
|
|
|
|
|
|
LogPrintf("ERROR: Proxy returned error %d\n", pchRet[1]); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
LogPrintf("SOCKS4 connected %s\n", addrDest.ToString()); |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool static Socks5(string strDest, int port, SOCKET& hSocket) |
|
|
|
bool static Socks5(string strDest, int port, SOCKET& hSocket) |
|
|
|
{ |
|
|
|
{ |
|
|
|
LogPrintf("SOCKS5 connecting %s\n", strDest); |
|
|
|
LogPrintf("SOCKS5 connecting %s\n", strDest); |
|
|
@ -468,53 +424,49 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool SetProxy(enum Network net, CService addrProxy, int nSocksVersion) { |
|
|
|
bool SetProxy(enum Network net, CService addrProxy) { |
|
|
|
assert(net >= 0 && net < NET_MAX); |
|
|
|
assert(net >= 0 && net < NET_MAX); |
|
|
|
if (nSocksVersion != 0 && nSocksVersion != 4 && nSocksVersion != 5) |
|
|
|
if (!addrProxy.IsValid()) |
|
|
|
return false; |
|
|
|
|
|
|
|
if (nSocksVersion != 0 && !addrProxy.IsValid()) |
|
|
|
|
|
|
|
return false; |
|
|
|
return false; |
|
|
|
LOCK(cs_proxyInfos); |
|
|
|
LOCK(cs_proxyInfos); |
|
|
|
proxyInfo[net] = std::make_pair(addrProxy, nSocksVersion); |
|
|
|
proxyInfo[net] = addrProxy; |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool GetProxy(enum Network net, proxyType &proxyInfoOut) { |
|
|
|
bool GetProxy(enum Network net, proxyType &proxyInfoOut) { |
|
|
|
assert(net >= 0 && net < NET_MAX); |
|
|
|
assert(net >= 0 && net < NET_MAX); |
|
|
|
LOCK(cs_proxyInfos); |
|
|
|
LOCK(cs_proxyInfos); |
|
|
|
if (!proxyInfo[net].second) |
|
|
|
if (!proxyInfo[net].IsValid()) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
proxyInfoOut = proxyInfo[net]; |
|
|
|
proxyInfoOut = proxyInfo[net]; |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool SetNameProxy(CService addrProxy, int nSocksVersion) { |
|
|
|
bool SetNameProxy(CService addrProxy) { |
|
|
|
if (nSocksVersion != 0 && nSocksVersion != 5) |
|
|
|
if (!addrProxy.IsValid()) |
|
|
|
return false; |
|
|
|
|
|
|
|
if (nSocksVersion != 0 && !addrProxy.IsValid()) |
|
|
|
|
|
|
|
return false; |
|
|
|
return false; |
|
|
|
LOCK(cs_proxyInfos); |
|
|
|
LOCK(cs_proxyInfos); |
|
|
|
nameproxyInfo = std::make_pair(addrProxy, nSocksVersion); |
|
|
|
nameProxy = addrProxy; |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool GetNameProxy(proxyType &nameproxyInfoOut) { |
|
|
|
bool GetNameProxy(CService &nameProxyOut) { |
|
|
|
LOCK(cs_proxyInfos); |
|
|
|
LOCK(cs_proxyInfos); |
|
|
|
if (!nameproxyInfo.second) |
|
|
|
if(!nameProxy.IsValid()) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
nameproxyInfoOut = nameproxyInfo; |
|
|
|
nameProxyOut = nameProxy; |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool HaveNameProxy() { |
|
|
|
bool HaveNameProxy() { |
|
|
|
LOCK(cs_proxyInfos); |
|
|
|
LOCK(cs_proxyInfos); |
|
|
|
return nameproxyInfo.second != 0; |
|
|
|
return nameProxy.IsValid(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool IsProxy(const CNetAddr &addr) { |
|
|
|
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 (proxyInfo[i].second && (addr == (CNetAddr)proxyInfo[i].first)) |
|
|
|
if (addr == (CNetAddr)proxyInfo[i]) |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
return false; |
|
|
|
return false; |
|
|
@ -523,31 +475,18 @@ bool IsProxy(const CNetAddr &addr) { |
|
|
|
bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout) |
|
|
|
bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout) |
|
|
|
{ |
|
|
|
{ |
|
|
|
proxyType proxy; |
|
|
|
proxyType proxy; |
|
|
|
|
|
|
|
// no proxy needed (none set for target network)
|
|
|
|
// no proxy needed
|
|
|
|
|
|
|
|
if (!GetProxy(addrDest.GetNetwork(), proxy)) |
|
|
|
if (!GetProxy(addrDest.GetNetwork(), proxy)) |
|
|
|
return ConnectSocketDirectly(addrDest, hSocketRet, nTimeout); |
|
|
|
return ConnectSocketDirectly(addrDest, hSocketRet, nTimeout); |
|
|
|
|
|
|
|
|
|
|
|
SOCKET hSocket = INVALID_SOCKET; |
|
|
|
SOCKET hSocket = INVALID_SOCKET; |
|
|
|
|
|
|
|
|
|
|
|
// first connect to proxy server
|
|
|
|
// first connect to proxy server
|
|
|
|
if (!ConnectSocketDirectly(proxy.first, hSocket, nTimeout)) |
|
|
|
if (!ConnectSocketDirectly(proxy, hSocket, nTimeout)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
// do socks negotiation
|
|
|
|
// do socks negotiation
|
|
|
|
switch (proxy.second) { |
|
|
|
if (!Socks5(addrDest.ToStringIP(), addrDest.GetPort(), hSocket)) |
|
|
|
case 4: |
|
|
|
|
|
|
|
if (!Socks4(addrDest, hSocket)) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case 5: |
|
|
|
|
|
|
|
if (!Socks5(addrDest.ToStringIP(), addrDest.GetPort(), hSocket)) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
closesocket(hSocket); |
|
|
|
|
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hSocketRet = hSocket; |
|
|
|
hSocketRet = hSocket; |
|
|
|
return true; |
|
|
|
return true; |
|
|
@ -561,30 +500,25 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest |
|
|
|
|
|
|
|
|
|
|
|
SOCKET hSocket = INVALID_SOCKET; |
|
|
|
SOCKET hSocket = INVALID_SOCKET; |
|
|
|
|
|
|
|
|
|
|
|
proxyType nameproxy; |
|
|
|
CService nameProxy; |
|
|
|
GetNameProxy(nameproxy); |
|
|
|
GetNameProxy(nameProxy); |
|
|
|
|
|
|
|
|
|
|
|
CService addrResolved(CNetAddr(strDest, fNameLookup && !nameproxy.second), port); |
|
|
|
CService addrResolved(CNetAddr(strDest, fNameLookup && !HaveNameProxy()), port); |
|
|
|
if (addrResolved.IsValid()) { |
|
|
|
if (addrResolved.IsValid()) { |
|
|
|
addr = addrResolved; |
|
|
|
addr = addrResolved; |
|
|
|
return ConnectSocket(addr, hSocketRet, nTimeout); |
|
|
|
return ConnectSocket(addr, hSocketRet, nTimeout); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
addr = CService("0.0.0.0:0"); |
|
|
|
addr = CService("0.0.0.0:0"); |
|
|
|
if (!nameproxy.second) |
|
|
|
|
|
|
|
|
|
|
|
if (!HaveNameProxy()) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
if (!ConnectSocketDirectly(nameproxy.first, hSocket, nTimeout)) |
|
|
|
// first connect to name proxy server
|
|
|
|
|
|
|
|
if (!ConnectSocketDirectly(nameProxy, hSocket, nTimeout)) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
// do socks negotiation
|
|
|
|
|
|
|
|
if (!Socks5(strDest, (unsigned short)port, hSocket)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
switch(nameproxy.second) { |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
case 4: |
|
|
|
|
|
|
|
closesocket(hSocket); |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
case 5: |
|
|
|
|
|
|
|
if (!Socks5(strDest, port, hSocket)) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hSocketRet = hSocket; |
|
|
|
hSocketRet = hSocket; |
|
|
|
return true; |
|
|
|
return true; |
|
|
|