Improve parsing of IPv6 addresses
Implement the following rules: * Interpret [X]:Y as host=X port=Y, if Y is an integer * Interpret X:Y as host=X port=Y, if Y is an integer and X contains no colon * Interpret X:Y as host=X:Y port=default otherwise
This commit is contained in:
parent
d59bce21e5
commit
1e8aeae15a
2 changed files with 27 additions and 43 deletions
|
@ -33,6 +33,27 @@ enum Network ParseNetwork(std::string net) {
|
||||||
return NET_UNROUTABLE;
|
return NET_UNROUTABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SplitHostPort(std::string in, int &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;
|
||||||
|
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
|
||||||
|
bool fMultiColon = fHaveColon && (in.find_last_of(':',colon-1) != in.npos);
|
||||||
|
if (fHaveColon && (colon==0 || fBracketed || !fMultiColon)) {
|
||||||
|
char *endp = NULL;
|
||||||
|
int n = strtol(in.c_str() + colon + 1, &endp, 10);
|
||||||
|
if (endp && *endp == 0 && n >= 0) {
|
||||||
|
in = in.substr(0, colon);
|
||||||
|
if (n > 0 && n < 0x10000)
|
||||||
|
portOut = n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (in.size()>0 && in[0] == '[' && in[in.size()-1] == ']')
|
||||||
|
hostOut = in.substr(1, in.size()-2);
|
||||||
|
else
|
||||||
|
hostOut = in;
|
||||||
|
}
|
||||||
|
|
||||||
bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
|
bool static LookupIntern(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup)
|
||||||
{
|
{
|
||||||
vIP.clear();
|
vIP.clear();
|
||||||
|
@ -114,36 +135,11 @@ bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault,
|
||||||
if (pszName[0] == 0)
|
if (pszName[0] == 0)
|
||||||
return false;
|
return false;
|
||||||
int port = portDefault;
|
int port = portDefault;
|
||||||
char psz[256];
|
std::string hostname = "";
|
||||||
char *pszHost = psz;
|
SplitHostPort(std::string(pszName), port, hostname);
|
||||||
strlcpy(psz, pszName, sizeof(psz));
|
|
||||||
char* pszColon = strrchr(psz+1,':');
|
|
||||||
char *pszPortEnd = NULL;
|
|
||||||
int portParsed = pszColon ? strtoul(pszColon+1, &pszPortEnd, 10) : 0;
|
|
||||||
if (pszColon && pszPortEnd && pszPortEnd[0] == 0)
|
|
||||||
{
|
|
||||||
if (psz[0] == '[' && pszColon[-1] == ']')
|
|
||||||
{
|
|
||||||
pszHost = psz+1;
|
|
||||||
pszColon[-1] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
pszColon[0] = 0;
|
|
||||||
if (port >= 0 && port <= USHRT_MAX)
|
|
||||||
port = portParsed;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (psz[0] == '[' && psz[strlen(psz)-1] == ']')
|
|
||||||
{
|
|
||||||
pszHost = psz+1;
|
|
||||||
psz[strlen(psz)-1] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<CNetAddr> vIP;
|
std::vector<CNetAddr> vIP;
|
||||||
bool fRet = LookupIntern(pszHost, vIP, nMaxSolutions, fAllowLookup);
|
bool fRet = LookupIntern(hostname.c_str(), vIP, nMaxSolutions, fAllowLookup);
|
||||||
if (!fRet)
|
if (!fRet)
|
||||||
return false;
|
return false;
|
||||||
vAddr.resize(vIP.size());
|
vAddr.resize(vIP.size());
|
||||||
|
@ -496,22 +492,9 @@ bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout)
|
||||||
|
|
||||||
bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout)
|
bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout)
|
||||||
{
|
{
|
||||||
string strDest(pszDest);
|
string strDest;
|
||||||
int port = portDefault;
|
int port = portDefault;
|
||||||
|
SplitHostPort(string(pszDest), port, strDest);
|
||||||
// split hostname and port
|
|
||||||
size_t colon = strDest.find_last_of(':');
|
|
||||||
if (colon != strDest.npos) {
|
|
||||||
char *endp = NULL;
|
|
||||||
int n = strtol(pszDest + colon + 1, &endp, 10);
|
|
||||||
if (endp && *endp == 0 && n >= 0) {
|
|
||||||
strDest = strDest.substr(0, colon);
|
|
||||||
if (n > 0 && n < 0x10000)
|
|
||||||
port = n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (strDest[0] == '[' && strDest[strDest.size()-1] == ']')
|
|
||||||
strDest = strDest.substr(1, strDest.size()-2);
|
|
||||||
|
|
||||||
SOCKET hSocket = INVALID_SOCKET;
|
SOCKET hSocket = INVALID_SOCKET;
|
||||||
CService addrResolved(CNetAddr(strDest, fNameLookup && !nameproxyInfo.second), port);
|
CService addrResolved(CNetAddr(strDest, fNameLookup && !nameproxyInfo.second), port);
|
||||||
|
|
|
@ -133,6 +133,7 @@ class CService : public CNetAddr
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Network ParseNetwork(std::string net);
|
enum Network ParseNetwork(std::string net);
|
||||||
|
void SplitHostPort(std::string in, int &portOut, std::string &hostOut);
|
||||||
bool SetProxy(enum Network net, CService addrProxy, int nSocksVersion = 5);
|
bool SetProxy(enum Network net, CService addrProxy, int nSocksVersion = 5);
|
||||||
bool GetProxy(enum Network net, CService &addrProxy);
|
bool GetProxy(enum Network net, CService &addrProxy);
|
||||||
bool IsProxy(const CNetAddr &addr);
|
bool IsProxy(const CNetAddr &addr);
|
||||||
|
|
Loading…
Reference in a new issue