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