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