130 lines
3.1 KiB
C++
130 lines
3.1 KiB
C++
![]() |
/* lw-support/src/lib/Net/Address/IPv4.cpp
|
||
|
*
|
||
|
* (c)2005, Laurence Withers. Released under the GNU GPL. See file
|
||
|
* COPYING for more information / terms of license.
|
||
|
*/
|
||
|
|
||
|
namespace lw {
|
||
|
|
||
|
|
||
|
|
||
|
const NetAddressIPv4 NetAddressIPv4::any(0, 0, 0, 0);
|
||
|
const NetAddressIPv4 NetAddressIPv4::loopback(127, 0, 0, 1);
|
||
|
|
||
|
|
||
|
|
||
|
std::wstring NetAddressIPv4::toString() const
|
||
|
{
|
||
|
std::wostringstream o;
|
||
|
|
||
|
o << (uint)(addr[0]) << L'.'
|
||
|
<< (uint)(addr[1]) << L'.'
|
||
|
<< (uint)(addr[2]) << L'.'
|
||
|
<< (uint)(addr[3]);
|
||
|
|
||
|
return o.str();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
NetAddressIPv4 NetAddressIPv4::fromString(const std::wstring& strIn)
|
||
|
{
|
||
|
std::wstring str = stripWhitespace(strIn);
|
||
|
|
||
|
uint8_t addr[4];
|
||
|
int addrPos = 0;
|
||
|
uint p = 0;
|
||
|
bool seen = false;
|
||
|
wchar_t ch;
|
||
|
|
||
|
std::wstring::size_type pos = 0, len = str.length();
|
||
|
|
||
|
for(pos = 0; pos < len; ++pos) {
|
||
|
ch = str[pos];
|
||
|
switch(ch) {
|
||
|
case '0' ... '9':
|
||
|
seen = true;
|
||
|
p *= 10;
|
||
|
p += (ch - '0');
|
||
|
if(p > 255) {
|
||
|
throw ParseError(L"Octet cannot be > 255.", str, pos)
|
||
|
.chain(L"NetAddressIPv4::fromString()");
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case '.':
|
||
|
if(!seen) {
|
||
|
throw ParseError(L"Empty octet.", str, pos)
|
||
|
.chain(L"NetAddressIPv4::fromString()");
|
||
|
}
|
||
|
if(addrPos == 3) {
|
||
|
throw ParseError(L"Too many octets.", str, pos)
|
||
|
.chain(L"NetAddressIPv4::fromString()");
|
||
|
}
|
||
|
|
||
|
addr[addrPos++] = p;
|
||
|
p = 0;
|
||
|
seen = false;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
throw ParseError(L"Unexpected symbol.", str, pos)
|
||
|
.chain(L"NetAddressIPv4::fromString()");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(addrPos != 3 || !seen) {
|
||
|
throw ParseError(L"Not enough octets.", str, pos)
|
||
|
.chain(L"NetAddressIPv4::fromString()");
|
||
|
}
|
||
|
|
||
|
addr[3] = p;
|
||
|
return NetAddressIPv4(addr);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
NetAddressIPv4 NetAddressIPv4::fromDNS(const std::string& host)
|
||
|
{
|
||
|
// attempt to convert from numeric form first
|
||
|
try {
|
||
|
return fromString(lw::asciiToUcs4(host));
|
||
|
}
|
||
|
catch(...) { }
|
||
|
|
||
|
// now perform blocking DNS lookup
|
||
|
struct hostent he, * hep = 0;
|
||
|
int err = 0, result = 0;
|
||
|
char buffer[4096];
|
||
|
|
||
|
result = gethostbyname2_r(host.c_str(), AF_INET,
|
||
|
&he, buffer, sizeof(buffer), &hep, &err);
|
||
|
switch(result) {
|
||
|
case 0:
|
||
|
// success!
|
||
|
break;
|
||
|
|
||
|
case HOST_NOT_FOUND:
|
||
|
throw DnsError(L"Host not found.", host);
|
||
|
|
||
|
case TRY_AGAIN:
|
||
|
throw DnsError(L"Temporary failure in name resolution.", host);
|
||
|
|
||
|
case NO_RECOVERY:
|
||
|
throw DnsError(L"Unrecoverable failure in name resolution.", host);
|
||
|
|
||
|
case NO_ADDRESS:
|
||
|
throw DnsError(L"Host does not have an associated IPv4 address.", host);
|
||
|
|
||
|
default:
|
||
|
throw DnsError(L"Unknown DNS error.", host);
|
||
|
}
|
||
|
|
||
|
|
||
|
return NetAddressIPv4(he.h_addr);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
}
|