Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:03:46

0001 ///////////////////////////////////////////////////////////////////////////////
0002 // Copyright (c) Lewis Baker
0003 // Licenced under MIT license. See LICENSE.txt for details.
0004 ///////////////////////////////////////////////////////////////////////////////
0005 #ifndef CPPCORO_NET_IPV6_ADDRESS_HPP_INCLUDED
0006 #define CPPCORO_NET_IPV6_ADDRESS_HPP_INCLUDED
0007 
0008 #include <cstdint>
0009 #include <optional>
0010 #include <string>
0011 #include <string_view>
0012 
0013 namespace cppcoro::net
0014 {
0015     class ipv4_address;
0016 
0017     class ipv6_address
0018     {
0019         using bytes_t = std::uint8_t[16];
0020 
0021     public:
0022 
0023         constexpr ipv6_address();
0024 
0025         explicit constexpr ipv6_address(
0026             std::uint64_t subnetPrefix,
0027             std::uint64_t interfaceIdentifier);
0028 
0029         constexpr ipv6_address(
0030             std::uint16_t part0,
0031             std::uint16_t part1,
0032             std::uint16_t part2,
0033             std::uint16_t part3,
0034             std::uint16_t part4,
0035             std::uint16_t part5,
0036             std::uint16_t part6,
0037             std::uint16_t part7);
0038 
0039         explicit constexpr ipv6_address(
0040             const std::uint16_t(&parts)[8]);
0041 
0042         explicit constexpr ipv6_address(
0043             const std::uint8_t(&bytes)[16]);
0044 
0045         constexpr const bytes_t& bytes() const { return m_bytes; }
0046 
0047         constexpr std::uint64_t subnet_prefix() const;
0048 
0049         constexpr std::uint64_t interface_identifier() const;
0050 
0051         /// Get the IPv6 unspedified address :: (all zeroes).
0052         static constexpr ipv6_address unspecified();
0053 
0054         /// Get the IPv6 loopback address ::1.
0055         static constexpr ipv6_address loopback();
0056 
0057         /// Parse a string representation of an IPv6 address.
0058         ///
0059         /// \param string
0060         /// The string to parse.
0061         /// Must be in ASCII, UTF-8 or Latin-1 encoding.
0062         ///
0063         /// \return
0064         /// The IP address if successful, otherwise std::nullopt if the string
0065         /// could not be parsed as an IPv4 address.
0066         static std::optional<ipv6_address> from_string(std::string_view string) noexcept;
0067 
0068         /// Convert the IP address to contracted string form.
0069         ///
0070         /// Address is broken up into 16-bit parts, with each part represended in 1-4
0071         /// lower-case hexadecimal with leading zeroes omitted. Parts are separated
0072         /// by separated by a ':'. The longest contiguous run of zero parts is contracted
0073         /// to "::".
0074         ///
0075         /// For example:
0076         /// ipv6_address::unspecified() -> "::"
0077         /// ipv6_address::loopback() -> "::1"
0078         /// ipv6_address(0x0011223344556677, 0x8899aabbccddeeff) ->
0079         ///   "11:2233:4455:6677:8899:aabb:ccdd:eeff"
0080         /// ipv6_address(0x0102030400000000, 0x003fc447ab991011) ->
0081         ///   "102:304::3f:c447:ab99:1011"
0082         std::string to_string() const;
0083 
0084         constexpr bool operator==(const ipv6_address& other) const;
0085         constexpr bool operator!=(const ipv6_address& other) const;
0086         constexpr bool operator<(const ipv6_address& other) const;
0087         constexpr bool operator>(const ipv6_address& other) const;
0088         constexpr bool operator<=(const ipv6_address& other) const;
0089         constexpr bool operator>=(const ipv6_address& other) const;
0090 
0091     private:
0092 
0093         alignas(std::uint64_t) std::uint8_t m_bytes[16];
0094 
0095     };
0096 
0097     constexpr ipv6_address::ipv6_address()
0098         : m_bytes{
0099             0, 0, 0, 0, 0, 0, 0, 0,
0100             0, 0, 0, 0, 0, 0, 0, 0 }
0101     {}
0102 
0103     constexpr ipv6_address::ipv6_address(
0104         std::uint64_t subnetPrefix,
0105         std::uint64_t interfaceIdentifier)
0106         : m_bytes{
0107             static_cast<std::uint8_t>(subnetPrefix >> 56),
0108             static_cast<std::uint8_t>(subnetPrefix >> 48),
0109             static_cast<std::uint8_t>(subnetPrefix >> 40),
0110             static_cast<std::uint8_t>(subnetPrefix >> 32),
0111             static_cast<std::uint8_t>(subnetPrefix >> 24),
0112             static_cast<std::uint8_t>(subnetPrefix >> 16),
0113             static_cast<std::uint8_t>(subnetPrefix >> 8),
0114             static_cast<std::uint8_t>(subnetPrefix),
0115             static_cast<std::uint8_t>(interfaceIdentifier >> 56),
0116             static_cast<std::uint8_t>(interfaceIdentifier >> 48),
0117             static_cast<std::uint8_t>(interfaceIdentifier >> 40),
0118             static_cast<std::uint8_t>(interfaceIdentifier >> 32),
0119             static_cast<std::uint8_t>(interfaceIdentifier >> 24),
0120             static_cast<std::uint8_t>(interfaceIdentifier >> 16),
0121             static_cast<std::uint8_t>(interfaceIdentifier >> 8),
0122             static_cast<std::uint8_t>(interfaceIdentifier) }
0123     {}
0124 
0125     constexpr ipv6_address::ipv6_address(
0126         std::uint16_t part0,
0127         std::uint16_t part1,
0128         std::uint16_t part2,
0129         std::uint16_t part3,
0130         std::uint16_t part4,
0131         std::uint16_t part5,
0132         std::uint16_t part6,
0133         std::uint16_t part7)
0134         : m_bytes{
0135             static_cast<std::uint8_t>(part0 >> 8),
0136             static_cast<std::uint8_t>(part0),
0137             static_cast<std::uint8_t>(part1 >> 8),
0138             static_cast<std::uint8_t>(part1),
0139             static_cast<std::uint8_t>(part2 >> 8),
0140             static_cast<std::uint8_t>(part2),
0141             static_cast<std::uint8_t>(part3 >> 8),
0142             static_cast<std::uint8_t>(part3),
0143             static_cast<std::uint8_t>(part4 >> 8),
0144             static_cast<std::uint8_t>(part4),
0145             static_cast<std::uint8_t>(part5 >> 8),
0146             static_cast<std::uint8_t>(part5),
0147             static_cast<std::uint8_t>(part6 >> 8),
0148             static_cast<std::uint8_t>(part6),
0149             static_cast<std::uint8_t>(part7 >> 8),
0150             static_cast<std::uint8_t>(part7) }
0151     {}
0152 
0153     constexpr ipv6_address::ipv6_address(
0154         const std::uint16_t(&parts)[8])
0155         : ipv6_address(
0156             parts[0], parts[1], parts[2], parts[3],
0157             parts[4], parts[5], parts[6], parts[7])
0158     {}
0159 
0160     constexpr ipv6_address::ipv6_address(const std::uint8_t(&bytes)[16])
0161         : m_bytes{
0162             bytes[0], bytes[1], bytes[2], bytes[3],
0163             bytes[4], bytes[5], bytes[6], bytes[7],
0164             bytes[8], bytes[9], bytes[10], bytes[11],
0165             bytes[12], bytes[13], bytes[14], bytes[15] }
0166     {}
0167 
0168     constexpr std::uint64_t ipv6_address::subnet_prefix() const
0169     {
0170         return
0171             static_cast<std::uint64_t>(m_bytes[0]) << 56 |
0172             static_cast<std::uint64_t>(m_bytes[1]) << 48 |
0173             static_cast<std::uint64_t>(m_bytes[2]) << 40 |
0174             static_cast<std::uint64_t>(m_bytes[3]) << 32 |
0175             static_cast<std::uint64_t>(m_bytes[4]) << 24 |
0176             static_cast<std::uint64_t>(m_bytes[5]) << 16 |
0177             static_cast<std::uint64_t>(m_bytes[6]) << 8 |
0178             static_cast<std::uint64_t>(m_bytes[7]);
0179     }
0180 
0181     constexpr std::uint64_t ipv6_address::interface_identifier() const
0182     {
0183         return
0184             static_cast<std::uint64_t>(m_bytes[8]) << 56 |
0185             static_cast<std::uint64_t>(m_bytes[9]) << 48 |
0186             static_cast<std::uint64_t>(m_bytes[10]) << 40 |
0187             static_cast<std::uint64_t>(m_bytes[11]) << 32 |
0188             static_cast<std::uint64_t>(m_bytes[12]) << 24 |
0189             static_cast<std::uint64_t>(m_bytes[13]) << 16 |
0190             static_cast<std::uint64_t>(m_bytes[14]) << 8 |
0191             static_cast<std::uint64_t>(m_bytes[15]);
0192     }
0193 
0194     constexpr ipv6_address ipv6_address::unspecified()
0195     {
0196         return ipv6_address{};
0197     }
0198 
0199     constexpr ipv6_address ipv6_address::loopback()
0200     {
0201         return ipv6_address{ 0, 0, 0, 0, 0, 0, 0, 1 };
0202     }
0203 
0204     constexpr bool ipv6_address::operator==(const ipv6_address& other) const
0205     {
0206         for (int i = 0; i < 16; ++i)
0207         {
0208             if (m_bytes[i] != other.m_bytes[i]) return false;
0209         }
0210         return true;
0211     }
0212 
0213     constexpr bool ipv6_address::operator!=(const ipv6_address& other) const
0214     {
0215         return !(*this == other);
0216     }
0217 
0218     constexpr bool ipv6_address::operator<(const ipv6_address& other) const
0219     {
0220         for (int i = 0; i < 16; ++i)
0221         {
0222             if (m_bytes[i] != other.m_bytes[i])
0223                 return m_bytes[i] < other.m_bytes[i];
0224         }
0225 
0226         return false;
0227     }
0228 
0229     constexpr bool ipv6_address::operator>(const ipv6_address& other) const
0230     {
0231         return (other < *this);
0232     }
0233 
0234     constexpr bool ipv6_address::operator<=(const ipv6_address& other) const
0235     {
0236         return !(other < *this);
0237     }
0238 
0239     constexpr bool ipv6_address::operator>=(const ipv6_address& other) const
0240     {
0241         return !(*this < other);
0242     }
0243 }
0244 
0245 #endif