This commit is contained in:
malloc 2018-03-06 14:47:32 -06:00
parent e98512193f
commit cd85c3763d
2 changed files with 173 additions and 3 deletions

View file

@ -1,5 +1,141 @@
#include "net.hpp"
// BEGIN IPADDRESS CLASS
sosc::net::IpAddress::IpAddress() {
for(int i = 0; i < 8; ++i)
this->parts[i] = std::make_pair(0, 0);
}
bool sosc::net::IpAddress::Parse(const std::string& addr) {
std::string addr_trim = str::trim(addr);
auto parts = str::split(addr_trim, '.');
if(parts.size() == 4)
return ParseIPv4Parts(parts);
else if(parts.size() != 1)
return false;
parts = str::split(addr_trim, "::");
if(parts.size() == 1) {
if(ParseIPv6Part(parts[0], true) != 8)
return false;
} else if(parts.size() == 2) {
int left_cnt, right_cnt;
if((left_cnt = ParseIPv6Part(parts[0], true)) == -1)
return false;
if((right_cnt = ParseIPv6Part(parts[1], false)) == -1)
return false;
if(left_cnt + right_cnt > 8)
return false;
} else
return false;
return true;
}
bool sosc::net::IpAddress::ParseIPv4Parts
(const std::vector<std::string>& parts)
{
this->parts[5] = std::make_pair(0xFFFF, 0);
for(int i = 0; i < 4; ++i) {
addrpart_t* ptr = &(this->parts[i < 2 ? 6 : 7]);
std::string part = str::trim(parts[i]);
int part_int;
if(part == "")
return false;
else if(part == "*") {
part_int = 0;
ptr->second |= (i % 2 == 0) ? 0xC : 0x3;
} else {
try { part_int = std::stoi(part); }
catch(...) { return false; }
}
if(part_int < 0 || part_int > 255)
return false;
ptr->first |= (i % 2 == 0)
? part_int << 8
: part_int;
}
return true;
}
int sosc::net::IpAddress::ParseIPv6Part
(const std::string& addr_part, bool from_start)
{
if(str::trim(addr_part) == "")
return 0;
auto parts = str::split(addr_part, ':');
if(parts.size() > 8)
return -1;
for(int i = 0; i < parts.size(); ++i) {
addrpart_t* ptr =
&(this->parts[from_start ? i : 8 - parts.size() + i]);
std::string part = str::trim(parts[i]);
int part_len = part.length();
if(part_len > 4 || part_len == 0)
return -1;
if(part == "*") {
ptr->first = 0;
ptr->second = 0x0F;
continue;
}
for(int i = 0; i < part_len; ++i) {
if(part[i] == '*') {
part[i] = '0';
ptr->second |= 1 << (part_len - i - 1);
}
}
try { ptr->first = std::stoi(part, NULL, 16); }
catch(...) { return -1; }
}
return parts.size();
}
sosc::net::IpAddress::operator std::string () const {
return this->ToString();
}
sosc::net::IpAddress::operator const char* () const {
return this->ToString().c_str();
}
std::string sosc::net::IpAddress::ToString(bool force_ipv6) const {
return "TODO THIS";
}
bool sosc::net::IpAddress::IsIdentical(const IpAddress& rhs) const {
for(int i = 0; i < 8; ++i)
if(this->parts[i] != rhs.parts[i])
return false;
return true;
}
bool sosc::net::IpAddress::IsIPv4() const {
auto blank = std::make_pair<uint16_t, uint8_t>(0, 0);
for(int i = 0; i < 5; ++i)
if(this->parts[i] != blank)
return false;
if(this->parts[5] != std::make_pair<uint16_t, uint8_t>(0xFFFF, 0))
return false;
return true;
}
// END IPADDRESS CLASS
bool sosc::net::is_big_endian() {
static uint16_t check = 0xFF00;
if(check == 0xFF00)

View file

@ -5,6 +5,7 @@
#include <algorithm>
#include <string>
#include <cstring>
#include "string.hpp"
#undef HTONS
#undef HTONUS
@ -40,12 +41,45 @@ namespace sosc {
namespace net {
class IpAddress {
public:
// all strings taken as arguments will accept both IPv4 and IPv6 addrs
// IPv4 addrs will be stored as IPv6 in this format:
// 127.126.0.255
// -> ::FFFF:7F7E:FF
// ^ ^ ^ ^
// |--|-|-|----- UNIQUE PREFIX VALUE (decimal 65535)
// |-|-|----- FIRST OCTET AS HEXADECIMAL (127 -> 7F)
// |-|----- SECOND OCTET AS HEXADECIMAL (126 -> 7E)
// |---+- THIRD OCTET IS HIDDEN SINCE FOURTH IS LOWER
// +- (0.255 -> 00FF -{equiv. to}-> FF)
IpAddress();
bool Parse(const std::string& addr);
operator std::string () const;
operator const char* () const;
std::string ToString(bool force_ipv6 = false) const;
bool operator == (const IpAddress& rhs) const;
bool operator != (const IpAddress& rhs) const;
bool IsIdentical(const IpAddress& rhs) const;
bool IsIPv4() const;
private:
typedef std::pair<uint16_t, uint8_t> addrpart_t;
addrpart_t parts[8] = {};
// pair item 1 is the two bytes in an IPv6 address
// pair item 2 is a wildcard bitmask on the nibble in the address
// 4 msbits unused, 4 lsbits indicate wildcards if bit is set
// ex. ::F F F F (IPv6 address)
// 0 1 1 0 (bitmask)
// 4 3 2 1 (bit position where 1 is LSB)
// would treat the middle two nibbles as wildcards; so this ip
// would match eg. ::F00F, ::FAAF, ::FEAF etc.
static addrpart_t ParsePart(std::string part);
typedef std::pair<uint16_t, uint8_t> addrpart_t;
std::string tostr_cache;
addrpart_t parts[8];
bool ParseIPv4Parts(const std::vector<std:string>& parts);
int ParseIPv6Part(const std::string& addr_part, bool from_start);
};
bool is_big_endian();