lw-support/src/liblw-support/Net/Address/IPv4.cpp

130 lines
3.1 KiB
C++
Raw Normal View History

2006-08-25 00:09:46 +01:00
/* 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);
}
}