Upgrades to epee::net_utils::network_address

- internal nullptr checks
  - prevent modifications to network_address (shallow copy issues)
  - automagically works with any type containing interface functions
  - removed fnv1a hashing
  - ipv4_network_address now flattened with no base class
This commit is contained in:
Lee Clagett 2017-08-25 11:14:46 -04:00
parent a2041c9874
commit 8b00687735
11 changed files with 446 additions and 92 deletions

View file

@ -27,6 +27,7 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <array>
#include <boost/endian/conversion.hpp>
#include <boost/range/algorithm/equal.hpp>
#include <boost/range/algorithm_ext/iota.hpp>
#include <cstdint>
@ -42,7 +43,11 @@
# include <arpa/inet.h>
#endif
#include "boost/archive/portable_binary_iarchive.hpp"
#include "boost/archive/portable_binary_oarchive.hpp"
#include "hex.h"
#include "net/net_utils_base.h"
#include "p2p/net_peerlist_boost_serialization.h"
#include "span.h"
#include "string_tools.h"
@ -100,6 +105,40 @@ namespace
boost::range::iota(out, 0);
return out;
}
#define CHECK_EQUAL(lhs, rhs) \
EXPECT_TRUE( lhs == rhs ); \
EXPECT_TRUE( rhs == lhs ); \
EXPECT_FALSE( lhs != rhs ); \
EXPECT_FALSE( rhs != lhs ); \
EXPECT_FALSE( lhs < rhs ); \
EXPECT_FALSE( rhs < lhs ); \
EXPECT_TRUE( lhs <= rhs ); \
EXPECT_TRUE( rhs <= lhs ); \
EXPECT_FALSE( lhs > rhs ); \
EXPECT_FALSE( rhs > lhs ); \
EXPECT_TRUE( lhs >= rhs ); \
EXPECT_TRUE( rhs >= lhs )
#define CHECK_LESS(lhs, rhs) \
EXPECT_FALSE( lhs == rhs ); \
EXPECT_FALSE( rhs == lhs ); \
EXPECT_TRUE( lhs != rhs ); \
EXPECT_TRUE( rhs != lhs ); \
EXPECT_TRUE( lhs < rhs ); \
EXPECT_FALSE( rhs < lhs ); \
EXPECT_TRUE( lhs <= rhs ); \
EXPECT_FALSE( rhs <= lhs ); \
EXPECT_FALSE( lhs > rhs ); \
EXPECT_TRUE( rhs > lhs ); \
EXPECT_FALSE( lhs >= rhs ); \
EXPECT_TRUE( rhs >= lhs )
#ifdef BOOST_LITTLE_ENDIAN
#define CHECK_LESS_ENDIAN(lhs, rhs) CHECK_LESS( rhs , lhs )
#else
#define CHECK_LESS_ENDIAN(lhs, rhs) CHECK_LESS( lhs , rhs )
#endif
}
TEST(Span, Traits)
@ -419,3 +458,195 @@ TEST(StringTools, GetIpInt32)
EXPECT_EQ(htonl(0xff0aff00), ip);
}
TEST(NetUtils, IPv4NetworkAddress)
{
const auto ip1 = boost::endian::native_to_big(0x330012FFu);
const auto ip_loopback = boost::endian::native_to_big(0x7F000001u);
const auto ip_local = boost::endian::native_to_big(0x0A000000u);
epee::net_utils::ipv4_network_address address1{ip1, 65535};
CHECK_EQUAL(address1, address1);
EXPECT_STREQ("51.0.18.255:65535", address1.str().c_str());
EXPECT_STREQ("51.0.18.255", address1.host_str().c_str());
EXPECT_FALSE(address1.is_loopback());
EXPECT_FALSE(address1.is_local());
EXPECT_EQ(epee::net_utils::ipv4_network_address::ID, address1.get_type_id());
EXPECT_EQ(ip1, address1.ip());
EXPECT_EQ(65535, address1.port());
EXPECT_TRUE(epee::net_utils::ipv4_network_address{std::move(address1)} == address1);
EXPECT_TRUE(epee::net_utils::ipv4_network_address{address1} == address1);
const epee::net_utils::ipv4_network_address loopback{ip_loopback, 0};
CHECK_EQUAL(loopback, loopback);
CHECK_LESS_ENDIAN(address1, loopback);
EXPECT_STREQ("127.0.0.1:0", loopback.str().c_str());
EXPECT_STREQ("127.0.0.1", loopback.host_str().c_str());
EXPECT_TRUE(loopback.is_loopback());
EXPECT_FALSE(loopback.is_local());
EXPECT_EQ(epee::net_utils::ipv4_network_address::ID, address1.get_type_id());
EXPECT_EQ(ip_loopback, loopback.ip());
EXPECT_EQ(0, loopback.port());
const epee::net_utils::ipv4_network_address local{ip_local, 8080};
CHECK_EQUAL(local, local);
CHECK_LESS(local, address1);
CHECK_LESS(local, loopback);
EXPECT_FALSE(local.is_loopback());
EXPECT_TRUE(local.is_local());
epee::net_utils::ipv4_network_address address2{ip1, 55};
CHECK_EQUAL(address2, address2);
CHECK_LESS_ENDIAN(address2, loopback);
CHECK_LESS(local, address2);
EXPECT_STREQ("51.0.18.255:55", address2.str().c_str());
EXPECT_STREQ("51.0.18.255", address2.host_str().c_str());
address2 = std::move(address1);
CHECK_EQUAL(address2, address1);
address2 = local;
CHECK_EQUAL(address2, local);
CHECK_LESS(address2, address1);
{
std::stringstream stream;
{
boost::archive::portable_binary_oarchive ostream{stream};
ostream << address1;
}
{
boost::archive::portable_binary_iarchive istream{stream};
istream >> address2;
}
}
CHECK_EQUAL(address1, address2);
EXPECT_EQ(ip1, address2.ip());
EXPECT_EQ(65535, address2.port());
}
TEST(NetUtils, NetworkAddress)
{
const auto ip1 = boost::endian::native_to_big(0x330012FFu);
const auto ip_loopback = boost::endian::native_to_big(0x7F000001u);
const auto ip_local = boost::endian::native_to_big(0x0A000000u);
struct custom_address {
constexpr static bool equal(const custom_address&) noexcept { return false; }
constexpr static bool less(const custom_address&) noexcept { return false; }
constexpr static bool is_same_host(const custom_address&) noexcept { return false; }
constexpr static bool is_loopback() noexcept { return false; }
constexpr static bool is_local() noexcept { return false; }
static std::string str() { return {}; }
static std::string host_str() { return {}; }
constexpr static uint8_t get_type_id() noexcept { return uint8_t(-1); }
};
const epee::net_utils::network_address empty;
CHECK_EQUAL(empty, empty);
EXPECT_TRUE(empty.is_same_host(empty));
EXPECT_STREQ("<none>", empty.str().c_str());
EXPECT_STREQ("<none>", empty.host_str().c_str());
EXPECT_FALSE(empty.is_loopback());
EXPECT_FALSE(empty.is_local());
EXPECT_EQ(0, empty.get_type_id());
EXPECT_THROW(empty.as<custom_address>(), std::bad_cast);
epee::net_utils::network_address address1{
epee::net_utils::ipv4_network_address{ip1, 65535}
};
CHECK_EQUAL(address1, address1);
CHECK_EQUAL(epee::net_utils::network_address{address1}, address1);
CHECK_LESS(empty, address1);
EXPECT_TRUE(address1.is_same_host(address1));
EXPECT_FALSE(empty.is_same_host(address1));
EXPECT_FALSE(address1.is_same_host(empty));
EXPECT_STREQ("51.0.18.255:65535", address1.str().c_str());
EXPECT_STREQ("51.0.18.255", address1.host_str().c_str());
EXPECT_FALSE(address1.is_loopback());
EXPECT_FALSE(address1.is_local());
EXPECT_EQ(epee::net_utils::ipv4_network_address::ID, address1.get_type_id());
EXPECT_NO_THROW(address1.as<epee::net_utils::ipv4_network_address>());
EXPECT_THROW(address1.as<custom_address>(), std::bad_cast);
const epee::net_utils::network_address loopback{
epee::net_utils::ipv4_network_address{ip_loopback, 0}
};
CHECK_EQUAL(loopback, loopback);
CHECK_LESS(empty, loopback);
CHECK_LESS_ENDIAN(address1, loopback);
EXPECT_TRUE(loopback.is_same_host(loopback));
EXPECT_FALSE(loopback.is_same_host(address1));
EXPECT_FALSE(address1.is_same_host(loopback));
EXPECT_STREQ("127.0.0.1:0", loopback.str().c_str());
EXPECT_STREQ("127.0.0.1", loopback.host_str().c_str());
EXPECT_TRUE(loopback.is_loopback());
EXPECT_FALSE(loopback.is_local());
EXPECT_EQ(epee::net_utils::ipv4_network_address::ID, address1.get_type_id());
const epee::net_utils::network_address local{
epee::net_utils::ipv4_network_address{ip_local, 8080}
};
CHECK_EQUAL(local, local);
CHECK_LESS(local, loopback);
CHECK_LESS(local, address1);
EXPECT_FALSE(local.is_loopback());
EXPECT_TRUE(local.is_local());
epee::net_utils::network_address address2{
epee::net_utils::ipv4_network_address{ip1, 55}
};
CHECK_EQUAL(address2, address2);
CHECK_LESS(address2, address1);
CHECK_LESS(local, address2);
CHECK_LESS_ENDIAN(address2, loopback);
EXPECT_TRUE(address1.is_same_host(address2));
EXPECT_TRUE(address2.is_same_host(address1));
EXPECT_STREQ("51.0.18.255:55", address2.str().c_str());
EXPECT_STREQ("51.0.18.255", address2.host_str().c_str());
address2 = std::move(address1);
CHECK_EQUAL(address1, address1);
CHECK_EQUAL(empty, address1);
CHECK_LESS(address1, address2);
EXPECT_FALSE(address1.is_same_host(address2));
EXPECT_FALSE(address2.is_same_host(address1));
EXPECT_STREQ("51.0.18.255:65535", address2.str().c_str());
EXPECT_STREQ("51.0.18.255", address2.host_str().c_str());
EXPECT_FALSE(address1.is_loopback());
EXPECT_FALSE(address1.is_local());
EXPECT_THROW(address1.as<epee::net_utils::ipv4_network_address>(), std::bad_cast);
EXPECT_NO_THROW(address2.as<epee::net_utils::ipv4_network_address>());
address2 = local;
CHECK_EQUAL(address2, local);
CHECK_LESS(address1, address2);
EXPECT_TRUE(address2.is_same_host(local));
EXPECT_TRUE(local.is_same_host(address2));
EXPECT_FALSE(address2.is_same_host(address1));
EXPECT_FALSE(address1.is_same_host(address2));
{
std::stringstream stream;
{
boost::archive::portable_binary_oarchive ostream{stream};
ostream << address2;
}
{
boost::archive::portable_binary_iarchive istream{stream};
istream >> address1;
}
}
CHECK_EQUAL(address1, address2);
EXPECT_TRUE(address1.is_same_host(address2));
EXPECT_TRUE(address2.is_same_host(address1));
EXPECT_NO_THROW(address1.as<epee::net_utils::ipv4_network_address>());
address1 = custom_address{};
CHECK_EQUAL(address1, address1);
CHECK_LESS(address2, address1);
EXPECT_FALSE(address1.is_same_host(loopback));
EXPECT_FALSE(loopback.is_same_host(address1));
EXPECT_THROW(address1.as<epee::net_utils::ipv4_network_address>(), std::bad_cast);
EXPECT_NO_THROW(address1.as<custom_address>());
}