1
0
Fork 0
mirror of https://gitlab.com/niansa/libcrosscoro.git synced 2025-03-06 20:53:32 +01:00
libcrosscoro/inc/coro/net/ip_address.hpp
Josh Baldwin bc3b956ed3
udp_peer! (#33)
* udp_peer!

I hope using the udp peer makes sense on how udp packets are
sent and received now.  Time will tell!

* Fix broken benchmark tcp server listening race condition
2021-01-09 19:18:03 -07:00

108 lines
2.9 KiB
C++

#pragma once
#include <string>
#include <stdexcept>
#include <array>
#include <span>
#include <arpa/inet.h>
#include <cstring>
namespace coro::net
{
enum class domain_t : int
{
ipv4 = AF_INET,
ipv6 = AF_INET6
};
auto to_string(domain_t domain) -> const std::string&;
class ip_address
{
public:
static const constexpr size_t ipv4_len{4};
static const constexpr size_t ipv6_len{16};
ip_address() = default;
ip_address(std::span<const uint8_t> binary_address, domain_t domain = domain_t::ipv4)
: m_domain(domain)
{
if(m_domain == domain_t::ipv4 && binary_address.size() > ipv4_len)
{
throw std::runtime_error{"coro::net::ip_address provided binary ip address is too long"};
}
else if(binary_address.size() > ipv6_len)
{
throw std::runtime_error{"coro::net::ip_address provided binary ip address is too long"};
}
std::copy(binary_address.begin(), binary_address.end(), m_data.begin());
}
ip_address(const ip_address&) = default;
ip_address(ip_address&&) = default;
auto operator=(const ip_address&) noexcept -> ip_address& = default;
auto operator=(ip_address&&) noexcept -> ip_address& = default;
~ip_address() = default;
auto domain() const -> domain_t { return m_domain; }
auto data() const -> std::span<const uint8_t>
{
if(m_domain == domain_t::ipv4)
{
return std::span<const uint8_t>{m_data.data(), ipv4_len};
}
else
{
return std::span<const uint8_t>{m_data.data(), ipv6_len};
}
}
static auto from_string(const std::string& address, domain_t domain = domain_t::ipv4) -> ip_address
{
ip_address addr{};
addr.m_domain = domain;
auto success = inet_pton(static_cast<int>(addr.m_domain), address.data(), addr.m_data.data());
if(success != 1)
{
throw std::runtime_error{"coro::net::ip_address faild to convert from string"};
}
return addr;
}
auto to_string() const -> std::string
{
std::string output;
if(m_domain == domain_t::ipv4)
{
output.resize(INET_ADDRSTRLEN, '\0');
}
else
{
output.resize(INET6_ADDRSTRLEN, '\0');
}
auto success = inet_ntop(static_cast<int>(m_domain), m_data.data(), output.data(), output.length());
if(success != nullptr)
{
auto len = strnlen(success, output.length());
output.resize(len);
}
else
{
throw std::runtime_error{"coro::net::ip_address failed to convert to string representation"};
}
return output;
}
auto operator<=>(const ip_address& other) const = default;
private:
domain_t m_domain{domain_t::ipv4};
std::array<uint8_t, ipv6_len> m_data{};
};
} // namespace coro::net