typedef SSIZE_T ssize_t;
#endif
-#include "strlcpy.h"
#include <boost/algorithm/string/case_conv.hpp> // for to_lower()
+#include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith()
using namespace std;
boost::to_lower(net);
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) {
+void SplitHostPort(std::string in, uint16_t &portOut, std::string &hostOut) {
size_t 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;
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;
bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
{
- if (pszName[0] == 0)
+ std::string strHost(pszName);
+ if (strHost.empty())
return false;
- char psz[256];
- char *pszHost = psz;
- strlcpy(psz, pszName, sizeof(psz));
- if (psz[0] == '[' && psz[strlen(psz)-1] == ']')
+ if (boost::algorithm::starts_with(strHost, "[") && boost::algorithm::ends_with(strHost, "]"))
{
- pszHost = psz+1;
- psz[strlen(psz)-1] = 0;
+ strHost = strHost.substr(1, strHost.size() - 2);
}
- return LookupIntern(pszHost, vIP, nMaxSolutions, fAllowLookup);
-}
-
-bool LookupHostNumeric(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions)
-{
- return LookupHost(pszName, vIP, nMaxSolutions, false);
+ return LookupIntern(strHost.c_str(), vIP, nMaxSolutions, fAllowLookup);
}
-bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions)
+bool Lookup(const char *pszName, std::vector<CService>& vAddr, uint16_t portDefault, bool fAllowLookup, unsigned int nMaxSolutions)
{
if (pszName[0] == 0)
return false;
- int port = portDefault;
+ uint16_t port = portDefault;
std::string hostname = "";
SplitHostPort(std::string(pszName), port, hostname);
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<CService> vService;
bool fRet = Lookup(pszName, vService, portDefault, fAllowLookup, 1);
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);
}
printf("SOCKS4 connecting %s\n", addrDest.ToString().c_str());
if (!addrDest.IsIPv4())
{
- closesocket(hSocket);
+ CloseSocket(hSocket);
return error("Proxy destination is not IPv4");
}
char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
socklen_t len = sizeof(addr);
if (!addrDest.GetSockAddr((struct sockaddr*)&addr, &len) || addr.sin_family != AF_INET)
{
- closesocket(hSocket);
+ CloseSocket(hSocket);
return error("Cannot get proxy destination address");
}
memcpy(pszSocks4IP + 2, &addr.sin_port, 2);
int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
if (ret != nSize)
{
- closesocket(hSocket);
+ CloseSocket(hSocket);
return error("Error sending to proxy");
}
char pchRet[8];
if (recv(hSocket, pchRet, 8, 0) != 8)
{
- closesocket(hSocket);
+ CloseSocket(hSocket);
return error("Error reading proxy response");
}
if (pchRet[1] != 0x5a)
{
- closesocket(hSocket);
+ CloseSocket(hSocket);
if (pchRet[1] != 0x5b)
printf("ERROR: Proxy returned error %d\n", pchRet[1]);
return false;
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");
strSocks5 += strDest;
strSocks5 += static_cast<char>((port >> 8) & 0xFF);
strSocks5 += static_cast<char>((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");
}
if (pchRet2[2] != 0x00)
{
- closesocket(hSocket);
+ CloseSocket(hSocket);
return error("Error: malformed proxy response");
}
char pchRet3[256];
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());
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;
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);
#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;
}
}
#endif
{
printf("connect() failed: %i\n",WSAGetLastError());
- closesocket(hSocket);
+ CloseSocket(hSocket);
return false;
}
}
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;
}
return false;
break;
default:
+ CloseSocket(hSocket);
return false;
}
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;
+ uint16_t port = portDefault;
SplitHostPort(string(pszDest), port, strDest);
SOCKET hSocket = INVALID_SOCKET;
switch(nameproxy.second) {
default:
- case 4: return false;
+ case 4:
+ CloseSocket(hSocket);
+ return false;
case 5:
if (!Socks5(strDest, port, hSocket))
return false;
void CNetAddr::Init()
{
- memset(ip, 0, 16);
+ memset(ip, 0, sizeof(ip));
}
void CNetAddr::SetIP(const CNetAddr& ipIn)
*this = vIP[0];
}
-unsigned int CNetAddr::GetByte(int n) const
+uint8_t CNetAddr::GetByte(int n) const
{
return ip[15-n];
}
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
std::vector<unsigned char> CNetAddr::GetGroup() const
{
std::vector<unsigned char> vchRet;
- int nClass = NET_IPV6;
+ uint8_t nClass = NET_IPV6;
int nStartByte = 0;
int nBits = 16;
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
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;
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
*this = ip;
}
-CService::CService(const char *pszIpPort, int portDefault, bool fAllowLookup)
+CService::CService(const char *pszIpPort, uint16_t portDefault, bool fAllowLookup)
{
Init();
CService ip;
*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;
return ToStringIPPort();
}
-void CService::print() const
+void CService::SetPort(unsigned short 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;
}