10#include <system_error>
13#include <sys/socket.h>
15#include <fmt/format.h>
17USERVER_NAMESPACE_BEGIN
25template <std::size_t N>
26class AddressBase
final {
27 static_assert(N == 4 || N == 16,
"Address can only be 4 or 16 bytes size");
30 static constexpr std::size_t AddressSize = N;
31 using BytesType = std::array<
unsigned char, N>;
33 AddressBase()
noexcept : address_({0}) {}
34 explicit AddressBase(
const BytesType& address) : address_(address) {}
37 const BytesType&
GetBytes()
const noexcept {
return address_; }
39 friend bool operator==(
const AddressBase<N>& a1,
const AddressBase<N>& a2)
noexcept {
40 return a1.address_ == a2.address_;
43 friend bool operator!=(
const AddressBase<N>& a1,
const AddressBase<N>& a2)
noexcept {
44 return a1.address_ != a2.address_;
54using AddressV4 = AddressBase<4>;
59using AddressV6 = AddressBase<16>;
62inline constexpr bool kIsAddressType = std::is_same_v<T, AddressV4> || std::is_same_v<T, AddressV6>;
82template <
typename Address,
typename = std::enable_if_t<kIsAddressType<Address>>>
83class NetworkBase
final {
85 using AddressType = Address;
86 static constexpr unsigned char kMaximumPrefixLength = std::is_same_v<Address, AddressV4> ? 32 : 128;
88 NetworkBase()
noexcept =
default;
90 NetworkBase(
const AddressType& address,
unsigned short prefix_length)
91 : address_(address), prefix_length_(prefix_length) {
92 if (prefix_length > kMaximumPrefixLength) {
93 throw std::out_of_range(fmt::format(
94 "{} prefix length is too large", std::is_same_v<Address, AddressV4> ?
"NetworkV4" :
"NetworkV6"
107 const auto network_bytes = address_.GetBytes();
108 const auto address_bytes = address.GetBytes();
110 std::uint8_t diff = 0;
111 for (std::size_t byte_index = 0; byte_index < kMaximumPrefixLength / 8; ++byte_index) {
112 std::uint8_t mask_byte = 0;
113 if (byte_index == prefix_length_ / 8) {
114 mask_byte = ~((1 << (8 - prefix_length_ % 8)) - 1);
116 if (byte_index < prefix_length_ / 8) {
120 diff |= (network_bytes[byte_index] ^ address_bytes[byte_index]) & mask_byte;
125 friend bool operator==(
const NetworkBase<Address>& a,
const NetworkBase<Address>& b)
noexcept {
126 return a.address_ == b.address_ && a.prefix_length_ == b.prefix_length_;
129 friend bool operator!=(
const NetworkBase<Address>& a,
const NetworkBase<Address>& b)
noexcept {
return !(a == b); }
132 AddressType address_;
133 unsigned char prefix_length_ = 0;
139using NetworkV4 = NetworkBase<AddressV4>;
144using NetworkV6 = NetworkBase<AddressV6>;
173class InetNetwork
final {
175 enum class AddressFamily :
unsigned char { IPv4 = AF_INET, IPv6 = AF_INET6 };
179 InetNetwork(std::vector<
unsigned char>&& bytes,
unsigned char prefix_length, AddressFamily address_family);
190 friend bool operator==(
const InetNetwork& lhs,
const InetNetwork& rhs) {
191 return lhs.address_family_ == rhs.address_family_ && lhs.prefix_length_ == rhs.prefix_length_ &&
192 lhs.bytes_ == rhs.bytes_;
195 friend bool operator!=(
const InetNetwork& lhs,
const InetNetwork& rhs) {
return !operator==(lhs, rhs); }
198 std::vector<
unsigned char> bytes_;
199 unsigned char prefix_length_;
200 AddressFamily address_family_;
216class AddressSystemError
final :
public std::exception {
218 AddressSystemError(std::error_code code, std::string_view msg) : msg_(msg), code_(code) {}
221 const std::error_code&
Code()
const {
return code_; }
223 const char* what()
const noexcept final {
return msg_.c_str(); }
227 std::error_code code_;