xref: /aosp_15_r20/external/openscreen/platform/base/ip_address.h (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1*3f982cf4SFabien Sanglard // Copyright 2018 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard 
5*3f982cf4SFabien Sanglard #ifndef PLATFORM_BASE_IP_ADDRESS_H_
6*3f982cf4SFabien Sanglard #define PLATFORM_BASE_IP_ADDRESS_H_
7*3f982cf4SFabien Sanglard 
8*3f982cf4SFabien Sanglard #include <array>
9*3f982cf4SFabien Sanglard #include <cstdint>
10*3f982cf4SFabien Sanglard #include <ostream>
11*3f982cf4SFabien Sanglard #include <string>
12*3f982cf4SFabien Sanglard #include <type_traits>
13*3f982cf4SFabien Sanglard 
14*3f982cf4SFabien Sanglard #include "platform/base/error.h"
15*3f982cf4SFabien Sanglard 
16*3f982cf4SFabien Sanglard namespace openscreen {
17*3f982cf4SFabien Sanglard 
18*3f982cf4SFabien Sanglard class IPAddress {
19*3f982cf4SFabien Sanglard  public:
20*3f982cf4SFabien Sanglard   enum class Version {
21*3f982cf4SFabien Sanglard     kV4,
22*3f982cf4SFabien Sanglard     kV6,
23*3f982cf4SFabien Sanglard   };
24*3f982cf4SFabien Sanglard 
kAnyV4()25*3f982cf4SFabien Sanglard   static constexpr IPAddress kAnyV4() { return IPAddress{0, 0, 0, 0}; }
kAnyV6()26*3f982cf4SFabien Sanglard   static constexpr IPAddress kAnyV6() {
27*3f982cf4SFabien Sanglard     return IPAddress{0, 0, 0, 0, 0, 0, 0, 0};
28*3f982cf4SFabien Sanglard   }
kV4LoopbackAddress()29*3f982cf4SFabien Sanglard   static constexpr IPAddress kV4LoopbackAddress() {
30*3f982cf4SFabien Sanglard     return IPAddress{127, 0, 0, 1};
31*3f982cf4SFabien Sanglard   }
kV6LoopbackAddress()32*3f982cf4SFabien Sanglard   static constexpr IPAddress kV6LoopbackAddress() {
33*3f982cf4SFabien Sanglard     return IPAddress{0, 0, 0, 0, 0, 0, 0, 1};
34*3f982cf4SFabien Sanglard   }
35*3f982cf4SFabien Sanglard   static constexpr size_t kV4Size = 4;
36*3f982cf4SFabien Sanglard   static constexpr size_t kV6Size = 16;
37*3f982cf4SFabien Sanglard 
IPAddress()38*3f982cf4SFabien Sanglard   constexpr IPAddress() : version_(Version::kV4), bytes_({}) {}
39*3f982cf4SFabien Sanglard 
40*3f982cf4SFabien Sanglard   // |bytes| contains 4 octets for IPv4, or 8 hextets (16 bytes of big-endian
41*3f982cf4SFabien Sanglard   // shorts) for IPv6.
42*3f982cf4SFabien Sanglard   IPAddress(Version version, const uint8_t* bytes);
43*3f982cf4SFabien Sanglard 
44*3f982cf4SFabien Sanglard   // IPv4 constructors (IPAddress from 4 octets).
IPAddress(const std::array<uint8_t,4> & bytes)45*3f982cf4SFabien Sanglard   explicit constexpr IPAddress(const std::array<uint8_t, 4>& bytes)
46*3f982cf4SFabien Sanglard       : version_(Version::kV4),
47*3f982cf4SFabien Sanglard         bytes_{{bytes[0], bytes[1], bytes[2], bytes[3]}} {}
48*3f982cf4SFabien Sanglard 
IPAddress(const uint8_t (& b)[4])49*3f982cf4SFabien Sanglard   explicit constexpr IPAddress(const uint8_t (&b)[4])
50*3f982cf4SFabien Sanglard       : version_(Version::kV4), bytes_{{b[0], b[1], b[2], b[3]}} {}
51*3f982cf4SFabien Sanglard 
IPAddress(uint8_t b1,uint8_t b2,uint8_t b3,uint8_t b4)52*3f982cf4SFabien Sanglard   constexpr IPAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4)
53*3f982cf4SFabien Sanglard       : version_(Version::kV4), bytes_{{b1, b2, b3, b4}} {}
54*3f982cf4SFabien Sanglard 
55*3f982cf4SFabien Sanglard   // IPv6 constructors (IPAddress from 8 hextets).
IPAddress(const std::array<uint16_t,8> & hextets)56*3f982cf4SFabien Sanglard   explicit constexpr IPAddress(const std::array<uint16_t, 8>& hextets)
57*3f982cf4SFabien Sanglard       : IPAddress(hextets[0],
58*3f982cf4SFabien Sanglard                   hextets[1],
59*3f982cf4SFabien Sanglard                   hextets[2],
60*3f982cf4SFabien Sanglard                   hextets[3],
61*3f982cf4SFabien Sanglard                   hextets[4],
62*3f982cf4SFabien Sanglard                   hextets[5],
63*3f982cf4SFabien Sanglard                   hextets[6],
64*3f982cf4SFabien Sanglard                   hextets[7]) {}
65*3f982cf4SFabien Sanglard 
IPAddress(const uint16_t (& hextets)[8])66*3f982cf4SFabien Sanglard   explicit constexpr IPAddress(const uint16_t (&hextets)[8])
67*3f982cf4SFabien Sanglard       : IPAddress(hextets[0],
68*3f982cf4SFabien Sanglard                   hextets[1],
69*3f982cf4SFabien Sanglard                   hextets[2],
70*3f982cf4SFabien Sanglard                   hextets[3],
71*3f982cf4SFabien Sanglard                   hextets[4],
72*3f982cf4SFabien Sanglard                   hextets[5],
73*3f982cf4SFabien Sanglard                   hextets[6],
74*3f982cf4SFabien Sanglard                   hextets[7]) {}
75*3f982cf4SFabien Sanglard 
IPAddress(uint16_t h0,uint16_t h1,uint16_t h2,uint16_t h3,uint16_t h4,uint16_t h5,uint16_t h6,uint16_t h7)76*3f982cf4SFabien Sanglard   constexpr IPAddress(uint16_t h0,
77*3f982cf4SFabien Sanglard                       uint16_t h1,
78*3f982cf4SFabien Sanglard                       uint16_t h2,
79*3f982cf4SFabien Sanglard                       uint16_t h3,
80*3f982cf4SFabien Sanglard                       uint16_t h4,
81*3f982cf4SFabien Sanglard                       uint16_t h5,
82*3f982cf4SFabien Sanglard                       uint16_t h6,
83*3f982cf4SFabien Sanglard                       uint16_t h7)
84*3f982cf4SFabien Sanglard       : version_(Version::kV6),
85*3f982cf4SFabien Sanglard         bytes_{{
86*3f982cf4SFabien Sanglard             static_cast<uint8_t>(h0 >> 8),
87*3f982cf4SFabien Sanglard             static_cast<uint8_t>(h0),
88*3f982cf4SFabien Sanglard             static_cast<uint8_t>(h1 >> 8),
89*3f982cf4SFabien Sanglard             static_cast<uint8_t>(h1),
90*3f982cf4SFabien Sanglard             static_cast<uint8_t>(h2 >> 8),
91*3f982cf4SFabien Sanglard             static_cast<uint8_t>(h2),
92*3f982cf4SFabien Sanglard             static_cast<uint8_t>(h3 >> 8),
93*3f982cf4SFabien Sanglard             static_cast<uint8_t>(h3),
94*3f982cf4SFabien Sanglard             static_cast<uint8_t>(h4 >> 8),
95*3f982cf4SFabien Sanglard             static_cast<uint8_t>(h4),
96*3f982cf4SFabien Sanglard             static_cast<uint8_t>(h5 >> 8),
97*3f982cf4SFabien Sanglard             static_cast<uint8_t>(h5),
98*3f982cf4SFabien Sanglard             static_cast<uint8_t>(h6 >> 8),
99*3f982cf4SFabien Sanglard             static_cast<uint8_t>(h6),
100*3f982cf4SFabien Sanglard             static_cast<uint8_t>(h7 >> 8),
101*3f982cf4SFabien Sanglard             static_cast<uint8_t>(h7),
102*3f982cf4SFabien Sanglard         }} {}
103*3f982cf4SFabien Sanglard 
104*3f982cf4SFabien Sanglard   constexpr IPAddress(const IPAddress& o) noexcept = default;
105*3f982cf4SFabien Sanglard   constexpr IPAddress(IPAddress&& o) noexcept = default;
106*3f982cf4SFabien Sanglard   ~IPAddress() = default;
107*3f982cf4SFabien Sanglard 
108*3f982cf4SFabien Sanglard   constexpr IPAddress& operator=(const IPAddress& o) noexcept = default;
109*3f982cf4SFabien Sanglard   constexpr IPAddress& operator=(IPAddress&& o) noexcept = default;
110*3f982cf4SFabien Sanglard 
111*3f982cf4SFabien Sanglard   bool operator==(const IPAddress& o) const;
112*3f982cf4SFabien Sanglard   bool operator!=(const IPAddress& o) const;
113*3f982cf4SFabien Sanglard 
114*3f982cf4SFabien Sanglard   // IP address comparison rules are based on the following two principles:
115*3f982cf4SFabien Sanglard   // 1. newer versions are greater, e.g. IPv6 > IPv4
116*3f982cf4SFabien Sanglard   // 2. higher numerical values are greater, e.g. 192.168.0.1 > 10.0.0.1
117*3f982cf4SFabien Sanglard   bool operator<(const IPAddress& other) const;
118*3f982cf4SFabien Sanglard   bool operator>(const IPAddress& other) const { return other < *this; }
119*3f982cf4SFabien Sanglard   bool operator<=(const IPAddress& other) const { return !(other < *this); }
120*3f982cf4SFabien Sanglard   bool operator>=(const IPAddress& other) const { return !(*this < other); }
121*3f982cf4SFabien Sanglard   explicit operator bool() const;
122*3f982cf4SFabien Sanglard 
version()123*3f982cf4SFabien Sanglard   Version version() const { return version_; }
IsV4()124*3f982cf4SFabien Sanglard   bool IsV4() const { return version_ == Version::kV4; }
IsV6()125*3f982cf4SFabien Sanglard   bool IsV6() const { return version_ == Version::kV6; }
126*3f982cf4SFabien Sanglard 
127*3f982cf4SFabien Sanglard   // These methods assume |x| is the appropriate size, but due to various
128*3f982cf4SFabien Sanglard   // callers' casting needs we can't check them like the constructors above.
129*3f982cf4SFabien Sanglard   // Callers should instead make any necessary checks themselves.
130*3f982cf4SFabien Sanglard   void CopyToV4(uint8_t* x) const;
131*3f982cf4SFabien Sanglard   void CopyToV6(uint8_t* x) const;
132*3f982cf4SFabien Sanglard 
133*3f982cf4SFabien Sanglard   // In some instances, we want direct access to the underlying byte storage,
134*3f982cf4SFabien Sanglard   // in order to avoid making multiple copies.
bytes()135*3f982cf4SFabien Sanglard   const uint8_t* bytes() const { return bytes_.data(); }
136*3f982cf4SFabien Sanglard 
137*3f982cf4SFabien Sanglard   // Parses a text representation of an IPv4 address (e.g. "192.168.0.1") or an
138*3f982cf4SFabien Sanglard   // IPv6 address (e.g. "abcd::1234").
139*3f982cf4SFabien Sanglard   static ErrorOr<IPAddress> Parse(const std::string& s);
140*3f982cf4SFabien Sanglard 
141*3f982cf4SFabien Sanglard  private:
142*3f982cf4SFabien Sanglard   Version version_;
143*3f982cf4SFabien Sanglard   std::array<uint8_t, 16> bytes_;
144*3f982cf4SFabien Sanglard };
145*3f982cf4SFabien Sanglard 
146*3f982cf4SFabien Sanglard struct IPEndpoint {
147*3f982cf4SFabien Sanglard  public:
148*3f982cf4SFabien Sanglard   IPAddress address;
149*3f982cf4SFabien Sanglard   uint16_t port = 0;
150*3f982cf4SFabien Sanglard 
151*3f982cf4SFabien Sanglard   // Used with various socket types to indicate "any" address.
152*3f982cf4SFabien Sanglard   static const IPEndpoint kAnyV4();
153*3f982cf4SFabien Sanglard   static const IPEndpoint kAnyV6();
154*3f982cf4SFabien Sanglard   explicit operator bool() const;
155*3f982cf4SFabien Sanglard 
156*3f982cf4SFabien Sanglard   // Parses a text representation of an IPv4/IPv6 address and port (e.g.
157*3f982cf4SFabien Sanglard   // "192.168.0.1:8080" or "[abcd::1234]:8080").
158*3f982cf4SFabien Sanglard   static ErrorOr<IPEndpoint> Parse(const std::string& s);
159*3f982cf4SFabien Sanglard 
160*3f982cf4SFabien Sanglard   std::string ToString() const;
161*3f982cf4SFabien Sanglard };
162*3f982cf4SFabien Sanglard 
163*3f982cf4SFabien Sanglard bool operator==(const IPEndpoint& a, const IPEndpoint& b);
164*3f982cf4SFabien Sanglard bool operator!=(const IPEndpoint& a, const IPEndpoint& b);
165*3f982cf4SFabien Sanglard 
166*3f982cf4SFabien Sanglard bool operator<(const IPEndpoint& a, const IPEndpoint& b);
167*3f982cf4SFabien Sanglard inline bool operator>(const IPEndpoint& a, const IPEndpoint& b) {
168*3f982cf4SFabien Sanglard   return b < a;
169*3f982cf4SFabien Sanglard }
170*3f982cf4SFabien Sanglard inline bool operator<=(const IPEndpoint& a, const IPEndpoint& b) {
171*3f982cf4SFabien Sanglard   return !(a > b);
172*3f982cf4SFabien Sanglard }
173*3f982cf4SFabien Sanglard inline bool operator>=(const IPEndpoint& a, const IPEndpoint& b) {
174*3f982cf4SFabien Sanglard   return !(a < b);
175*3f982cf4SFabien Sanglard }
176*3f982cf4SFabien Sanglard 
177*3f982cf4SFabien Sanglard // Outputs a string of the form:
178*3f982cf4SFabien Sanglard //      123.234.34.56
179*3f982cf4SFabien Sanglard //   or fe80:0000:0000:0000:1234:5678:9abc:def0
180*3f982cf4SFabien Sanglard std::ostream& operator<<(std::ostream& out, const IPAddress& address);
181*3f982cf4SFabien Sanglard 
182*3f982cf4SFabien Sanglard // Outputs a string of the form:
183*3f982cf4SFabien Sanglard //      123.234.34.56:443
184*3f982cf4SFabien Sanglard //   or [fe80:0000:0000:0000:1234:5678:9abc:def0]:8080
185*3f982cf4SFabien Sanglard std::ostream& operator<<(std::ostream& out, const IPEndpoint& endpoint);
186*3f982cf4SFabien Sanglard 
187*3f982cf4SFabien Sanglard }  // namespace openscreen
188*3f982cf4SFabien Sanglard 
189*3f982cf4SFabien Sanglard #endif  // PLATFORM_BASE_IP_ADDRESS_H_
190