X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fnetbase.cpp;h=968d6c622c1a427d48abd07b894831044f2a6209;hb=6229d2798d9e3777a8afaf598c38ebf542ccf797;hp=f7975f488bb549cf592340d2dc9f01a517601abb;hpb=5bd1916925c35f699a35716e0c6b123a5389f633;p=novacoin.git diff --git a/src/netbase.cpp b/src/netbase.cpp index f7975f4..968d6c6 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -9,22 +9,23 @@ #include "hash.h" #ifndef WIN32 +#ifdef ANDROID +#include +#else #include #endif +#endif #ifdef _MSC_VER #include typedef SSIZE_T ssize_t; #endif -#include "strlcpy.h" -#include // for to_lower() - using namespace std; // Settings static proxyType proxyInfo[NET_MAX]; -static proxyType nameproxyInfo; +static CService nameProxy; static CCriticalSection cs_proxyInfos; int nConnectTimeout = 5000; bool fNameLookup = false; @@ -32,16 +33,16 @@ bool fNameLookup = false; static const unsigned char pchIPv4[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff }; enum Network ParseNetwork(std::string net) { - boost::to_lower(net); + transform(net.begin(), net.end(), net.begin(), ::tolower); if (net == "ipv4") return NET_IPV4; if (net == "ipv6") return NET_IPV6; - if (net == "tor") return NET_TOR; + if (net == "tor" || net == "onion") return NET_TOR; if (net == "i2p") return NET_I2P; return NET_UNROUTABLE; } -void SplitHostPort(std::string in, int &portOut, std::string &hostOut) { - size_t colon = in.find_last_of(':'); +void SplitHostPort(std::string in, uint16_t &portOut, std::string &hostOut) { + auto colon = in.find_last_of(':'); // if a : is found, and it either follows a [...], or no other : is in the string, treat it as port separator bool fHaveColon = colon != in.npos; bool fBracketed = fHaveColon && (in[0]=='[' && in[colon-1]==']'); // if there is a colon, and in[0]=='[', colon is not 0, so in[colon-1] is safe @@ -78,19 +79,14 @@ bool static LookupIntern(const char *pszName, std::vector& vIP, unsign aiHint.ai_socktype = SOCK_STREAM; aiHint.ai_protocol = IPPROTO_TCP; -#ifdef WIN32 -# ifdef USE_IPV6 +#ifdef USE_IPV6 aiHint.ai_family = AF_UNSPEC; -# else +#else aiHint.ai_family = AF_INET; -# endif +#endif +#ifdef WIN32 aiHint.ai_flags = fAllowLookup ? 0 : AI_NUMERICHOST; #else -# ifdef USE_IPV6 - aiHint.ai_family = AF_UNSPEC; -# else - aiHint.ai_family = AF_INET; -# endif aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST; #endif struct addrinfo *aiRes = NULL; @@ -101,19 +97,20 @@ bool static LookupIntern(const char *pszName, std::vector& vIP, unsign struct addrinfo *aiTrav = aiRes; while (aiTrav != NULL && (nMaxSolutions == 0 || vIP.size() < nMaxSolutions)) { - if (aiTrav->ai_family == AF_INET) + switch (aiTrav->ai_family) { - assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in)); - vIP.push_back(CNetAddr(((struct sockaddr_in*)(aiTrav->ai_addr))->sin_addr)); - } + case (AF_INET): + assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in)); + vIP.push_back(CNetAddr(((struct sockaddr_in*)(aiTrav->ai_addr))->sin_addr)); + break; #ifdef USE_IPV6 - if (aiTrav->ai_family == AF_INET6) - { - assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6)); - vIP.push_back(CNetAddr(((struct sockaddr_in6*)(aiTrav->ai_addr))->sin6_addr)); - } + case (AF_INET6): + assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6)); + vIP.push_back(CNetAddr(((struct sockaddr_in6*)(aiTrav->ai_addr))->sin6_addr)); + break; #endif + } aiTrav = aiTrav->ai_next; } @@ -123,32 +120,37 @@ bool static LookupIntern(const char *pszName, std::vector& vIP, unsign return (vIP.size() > 0); } -bool LookupHost(const char *pszName, std::vector& vIP, unsigned int nMaxSolutions, bool fAllowLookup) +bool LookupHost(const string& strName, std::vector& vIP, unsigned int nMaxSolutions, bool fAllowLookup) { - if (pszName[0] == 0) + std::string strHost(strName); + if (strHost.empty()) return false; - char psz[256]; - char *pszHost = psz; - strlcpy(psz, pszName, sizeof(psz)); - if (psz[0] == '[' && psz[strlen(psz)-1] == ']') + if ((strHost.front() == '[') && (strHost.back() == ']')) { - pszHost = psz+1; - psz[strlen(psz)-1] = 0; + strHost = strHost.substr(1, strHost.size() - 2); } - return LookupIntern(pszHost, vIP, nMaxSolutions, fAllowLookup); + return LookupIntern(strHost.c_str(), vIP, nMaxSolutions, fAllowLookup); } -bool LookupHostNumeric(const char *pszName, std::vector& vIP, unsigned int nMaxSolutions) +bool LookupHost(const char *pszName, std::vector& vIP, unsigned int nMaxSolutions, bool fAllowLookup) { - return LookupHost(pszName, vIP, nMaxSolutions, false); + std::string strHost(pszName); + if (strHost.empty()) + return false; + if ((strHost.front() == '[') && (strHost.back() == ']')) + { + strHost = strHost.substr(1, strHost.size() - 2); + } + + return LookupIntern(strHost.c_str(), vIP, nMaxSolutions, fAllowLookup); } -bool Lookup(const char *pszName, std::vector& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions) +bool Lookup(const char *pszName, std::vector& vAddr, uint16_t portDefault, bool fAllowLookup, unsigned int nMaxSolutions) { if (pszName[0] == 0) return false; - int port = portDefault; + auto port = portDefault; std::string hostname = ""; SplitHostPort(std::string(pszName), port, hostname); @@ -162,7 +164,7 @@ bool Lookup(const char *pszName, std::vector& vAddr, int portDefault, return true; } -bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup) +bool Lookup(const char *pszName, CService& addr, uint16_t portDefault, bool fAllowLookup) { std::vector vService; bool fRet = Lookup(pszName, vService, portDefault, fAllowLookup, 1); @@ -172,82 +174,35 @@ bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLoo return true; } -bool LookupNumeric(const char *pszName, CService& addr, int portDefault) +bool LookupNumeric(const char *pszName, CService& addr, uint16_t portDefault) { return Lookup(pszName, addr, portDefault, false); } -bool static Socks4(const CService &addrDest, SOCKET& hSocket) -{ - printf("SOCKS4 connecting %s\n", addrDest.ToString().c_str()); - 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) - printf("ERROR: Proxy returned error %d\n", pchRet[1]); - return false; - } - printf("SOCKS4 connected %s\n", addrDest.ToString().c_str()); - return true; -} - -bool static Socks5(string strDest, int port, SOCKET& hSocket) +bool static Socks5(string strDest, uint16_t port, SOCKET& hSocket) { printf("SOCKS5 connecting %s\n", strDest.c_str()); if (strDest.size() > 255) { - closesocket(hSocket); + CloseSocket(hSocket); return error("Hostname too long"); } - char pszSocks5Init[] = "\5\1\0"; - char *pszSocks5 = pszSocks5Init; - ssize_t nSize = sizeof(pszSocks5Init) - 1; - - ssize_t ret = send(hSocket, pszSocks5, nSize, MSG_NOSIGNAL); - if (ret != nSize) + const char pszSocks5Init[] = "\5\1\0"; + ssize_t ret = send(hSocket, pszSocks5Init, 3, MSG_NOSIGNAL); + if (ret != 3) { - closesocket(hSocket); + CloseSocket(hSocket); return error("Error sending to proxy"); } char pchRet1[2]; if (recv(hSocket, pchRet1, 2, 0) != 2) { - closesocket(hSocket); + CloseSocket(hSocket); return error("Error reading proxy response"); } if (pchRet1[0] != 0x05 || pchRet1[1] != 0x00) { - closesocket(hSocket); + CloseSocket(hSocket); return error("Proxy failed to initialize"); } string strSocks5("\5\1"); @@ -256,26 +211,26 @@ bool static Socks5(string strDest, int port, SOCKET& hSocket) strSocks5 += strDest; strSocks5 += static_cast((port >> 8) & 0xFF); strSocks5 += static_cast((port >> 0) & 0xFF); - ret = send(hSocket, strSocks5.c_str(), strSocks5.size(), MSG_NOSIGNAL); + ret = send(hSocket, strSocks5.data(), strSocks5.size(), MSG_NOSIGNAL); if (ret != (ssize_t)strSocks5.size()) { - closesocket(hSocket); + CloseSocket(hSocket); return error("Error sending to proxy"); } char pchRet2[4]; if (recv(hSocket, pchRet2, 4, 0) != 4) { - closesocket(hSocket); + CloseSocket(hSocket); return error("Error reading proxy response"); } if (pchRet2[0] != 0x05) { - closesocket(hSocket); + CloseSocket(hSocket); return error("Proxy failed to accept request"); } if (pchRet2[1] != 0x00) { - closesocket(hSocket); + CloseSocket(hSocket); switch (pchRet2[1]) { case 0x01: return error("Proxy error: general failure"); @@ -291,7 +246,7 @@ bool static Socks5(string strDest, int port, SOCKET& hSocket) } if (pchRet2[2] != 0x00) { - closesocket(hSocket); + CloseSocket(hSocket); return error("Error: malformed proxy response"); } char pchRet3[256]; @@ -302,22 +257,24 @@ bool static Socks5(string strDest, int port, SOCKET& hSocket) case 0x03: { ret = recv(hSocket, pchRet3, 1, 0) != 1; - if (ret) + if (ret) { + CloseSocket(hSocket); return error("Error reading from proxy"); + } int nRecv = pchRet3[0]; ret = recv(hSocket, pchRet3, nRecv, 0) != nRecv; break; } - default: closesocket(hSocket); return error("Error: malformed proxy response"); + default: CloseSocket(hSocket); return error("Error: malformed proxy response"); } if (ret) { - closesocket(hSocket); + CloseSocket(hSocket); return error("Error reading from proxy"); } if (recv(hSocket, pchRet3, 2, 0) != 2) { - closesocket(hSocket); + CloseSocket(hSocket); return error("Error reading from proxy"); } printf("SOCKS5 connected %s\n", strDest.c_str()); @@ -355,14 +312,15 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == -1) #endif { - closesocket(hSocket); + CloseSocket(hSocket); return false; } if (connect(hSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR) { + int nErr = WSAGetLastError(); // WSAEINVAL is here because some legacy version of winsock uses it - if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL) + if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK || nErr == WSAEINVAL) { struct timeval timeout; timeout.tv_sec = nTimeout / 1000; @@ -375,13 +333,13 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe if (nRet == 0) { printf("connection timeout\n"); - closesocket(hSocket); + CloseSocket(hSocket); return false; } if (nRet == SOCKET_ERROR) { printf("select() for connection failed: %i\n",WSAGetLastError()); - closesocket(hSocket); + CloseSocket(hSocket); return false; } socklen_t nRetSize = sizeof(nRet); @@ -392,13 +350,13 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe #endif { printf("getsockopt() for connection failed: %i\n",WSAGetLastError()); - closesocket(hSocket); + CloseSocket(hSocket); return false; } if (nRet != 0) { printf("connect() failed after select(): %s\n",strerror(nRet)); - closesocket(hSocket); + CloseSocket(hSocket); return false; } } @@ -409,7 +367,7 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe #endif { printf("connect() failed: %i\n",WSAGetLastError()); - closesocket(hSocket); + CloseSocket(hSocket); return false; } } @@ -422,10 +380,10 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR) #else fFlags = fcntl(hSocket, F_GETFL, 0); - if (fcntl(hSocket, F_SETFL, fFlags & !O_NONBLOCK) == SOCKET_ERROR) + if (fcntl(hSocket, F_SETFL, fFlags & ~O_NONBLOCK) == SOCKET_ERROR) #endif { - closesocket(hSocket); + CloseSocket(hSocket); return false; } @@ -433,53 +391,49 @@ bool static ConnectSocketDirectly(const CService &addrConnect, SOCKET& hSocketRe return true; } -bool SetProxy(enum Network net, CService addrProxy, int nSocksVersion) { +bool SetProxy(enum Network net, CService addrProxy) { assert(net >= 0 && net < NET_MAX); - if (nSocksVersion != 0 && nSocksVersion != 4 && nSocksVersion != 5) - return false; - if (nSocksVersion != 0 && !addrProxy.IsValid()) + if (!addrProxy.IsValid()) return false; LOCK(cs_proxyInfos); - proxyInfo[net] = std::make_pair(addrProxy, nSocksVersion); + proxyInfo[net] = addrProxy; return true; } bool GetProxy(enum Network net, proxyType &proxyInfoOut) { assert(net >= 0 && net < NET_MAX); LOCK(cs_proxyInfos); - if (!proxyInfo[net].second) + if (!proxyInfo[net].IsValid()) return false; proxyInfoOut = proxyInfo[net]; return true; } -bool SetNameProxy(CService addrProxy, int nSocksVersion) { - if (nSocksVersion != 0 && nSocksVersion != 5) - return false; - if (nSocksVersion != 0 && !addrProxy.IsValid()) +bool SetNameProxy(CService addrProxy) { + if (!addrProxy.IsValid()) return false; LOCK(cs_proxyInfos); - nameproxyInfo = std::make_pair(addrProxy, nSocksVersion); + nameProxy = addrProxy; return true; } -bool GetNameProxy(proxyType &nameproxyInfoOut) { +bool GetNameProxy(CService &nameProxyOut) { LOCK(cs_proxyInfos); - if (!nameproxyInfo.second) + if (!nameProxy.IsValid()) return false; - nameproxyInfoOut = nameproxyInfo; + nameProxyOut = nameProxy; return true; } bool HaveNameProxy() { LOCK(cs_proxyInfos); - return nameproxyInfo.second != 0; + return nameProxy.IsValid(); } bool IsProxy(const CNetAddr &addr) { LOCK(cs_proxyInfos); 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 false; @@ -496,57 +450,42 @@ bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout) SOCKET hSocket = INVALID_SOCKET; // first connect to proxy server - if (!ConnectSocketDirectly(proxy.first, hSocket, nTimeout)) + if (!ConnectSocketDirectly(proxy, hSocket, nTimeout)) return false; // do socks negotiation - switch (proxy.second) { - case 4: - if (!Socks4(addrDest, hSocket)) - return false; - break; - case 5: - if (!Socks5(addrDest.ToStringIP(), addrDest.GetPort(), hSocket)) - return false; - break; - default: + if (!Socks5(addrDest.ToStringIP(), addrDest.GetPort(), hSocket)) return false; - } hSocketRet = hSocket; return true; } -bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout) +bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, uint16_t portDefault, int nTimeout) { string strDest; - int port = portDefault; + auto port = portDefault; SplitHostPort(string(pszDest), port, strDest); SOCKET hSocket = INVALID_SOCKET; - proxyType nameproxy; - GetNameProxy(nameproxy); + CService nameProxy; + GetNameProxy(nameProxy); - CService addrResolved(CNetAddr(strDest, fNameLookup && !nameproxy.second), port); + CService addrResolved(CNetAddr(strDest, fNameLookup && !HaveNameProxy()), port); if (addrResolved.IsValid()) { addr = addrResolved; return ConnectSocket(addr, hSocketRet, nTimeout); } addr = CService("0.0.0.0:0"); - if (!nameproxy.second) + if (!HaveNameProxy()) 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, port, hSocket)) return false; - - switch(nameproxy.second) { - default: - case 4: return false; - case 5: - if (!Socks5(strDest, port, hSocket)) - return false; - break; - } hSocketRet = hSocket; return true; @@ -554,7 +493,7 @@ bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest void CNetAddr::Init() { - memset(ip, 0, 16); + memset(ip, 0, sizeof(ip)); } void CNetAddr::SetIP(const CNetAddr& ipIn) @@ -618,11 +557,11 @@ CNetAddr::CNetAddr(const std::string &strIp, bool fAllowLookup) { Init(); std::vector vIP; - if (LookupHost(strIp.c_str(), vIP, 1, fAllowLookup)) + if (LookupHost(strIp, vIP, 1, fAllowLookup)) *this = vIP[0]; } -unsigned int CNetAddr::GetByte(int n) const +uint8_t CNetAddr::GetByte(int n) const { return ip[15-n]; } @@ -787,7 +726,7 @@ std::string CNetAddr::ToStringIP() const return EncodeBase32(&ip[6], 10) + ".onion"; if (IsI2P()) return EncodeBase32(&ip[6], 10) + ".oc.b32.i2p"; - CService serv(*this, 0); + CService serv(*this, (uint16_t)0); #ifdef USE_IPV6 struct sockaddr_storage sockaddr; #else @@ -850,7 +789,7 @@ bool CNetAddr::GetIn6Addr(struct in6_addr* pipv6Addr) const std::vector CNetAddr::GetGroup() const { std::vector vchRet; - int nClass = NET_IPV6; + uint8_t nClass = NET_IPV6; int nStartByte = 0; int nBits = 16; @@ -901,7 +840,7 @@ std::vector CNetAddr::GetGroup() const nBits = 4; } // for he.net, use /36 groups - else if (GetByte(15) == 0x20 && GetByte(14) == 0x11 && GetByte(13) == 0x04 && GetByte(12) == 0x70) + else if (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x04 && GetByte(12) == 0x70) nBits = 36; // for the rest of the IPv6 network, use /32 groups else @@ -920,19 +859,14 @@ std::vector CNetAddr::GetGroup() const return vchRet; } -uint64 CNetAddr::GetHash() const +uint64_t CNetAddr::GetHash() const { - uint256 hash = Hash(&ip[0], &ip[16]); - uint64 nRet; + auto hash = Hash(&ip[0], &ip[16]); + uint64_t nRet; memcpy(&nRet, &hash, sizeof(nRet)); return nRet; } -void CNetAddr::print() const -{ - printf("CNetAddr(%s)\n", ToString().c_str()); -} - // private extensions to enum Network, only returned by GetExtNetwork, // and only used in GetReachabilityFrom static const int NET_UNKNOWN = NET_MAX + 0; @@ -1021,16 +955,16 @@ CService::CService() Init(); } -CService::CService(const CNetAddr& cip, unsigned short portIn) : CNetAddr(cip), port(portIn) +CService::CService(const CNetAddr& cip, uint16_t portIn) : CNetAddr(cip), port(portIn) { } -CService::CService(const struct in_addr& ipv4Addr, unsigned short portIn) : CNetAddr(ipv4Addr), port(portIn) +CService::CService(const struct in_addr& ipv4Addr, uint16_t portIn) : CNetAddr(ipv4Addr), port(portIn) { } #ifdef USE_IPV6 -CService::CService(const struct in6_addr& ipv6Addr, unsigned short portIn) : CNetAddr(ipv6Addr), port(portIn) +CService::CService(const struct in6_addr& ipv6Addr, uint16_t portIn) : CNetAddr(ipv6Addr), port(portIn) { } #endif @@ -1071,7 +1005,7 @@ CService::CService(const char *pszIpPort, bool fAllowLookup) *this = ip; } -CService::CService(const char *pszIpPort, int portDefault, bool fAllowLookup) +CService::CService(const char *pszIpPort, uint16_t portDefault, bool fAllowLookup) { Init(); CService ip; @@ -1087,7 +1021,7 @@ CService::CService(const std::string &strIpPort, bool fAllowLookup) *this = ip; } -CService::CService(const std::string &strIpPort, int portDefault, bool fAllowLookup) +CService::CService(const std::string &strIpPort, uint16_t portDefault, bool fAllowLookup) { Init(); CService ip; @@ -1095,7 +1029,7 @@ CService::CService(const std::string &strIpPort, int portDefault, bool fAllowLoo *this = ip; } -unsigned short CService::GetPort() const +uint16_t CService::GetPort() const { return port; } @@ -1175,12 +1109,20 @@ std::string CService::ToString() const return ToStringIPPort(); } -void CService::print() const +void CService::SetupPort(uint16_t portIn) { - printf("CService(%s)\n", ToString().c_str()); + port = portIn; } -void CService::SetPort(unsigned short portIn) +bool CloseSocket(SOCKET& hSocket) { - port = portIn; + if (hSocket == INVALID_SOCKET) + return false; +#ifdef WIN32 + int ret = closesocket(hSocket); +#else + int ret = close(hSocket); +#endif + hSocket = INVALID_SOCKET; + return ret != SOCKET_ERROR; }