Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
InternetAddress.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
6#include "Stroika/Foundation/Memory/Common.h"
8
10
11 /*
12 ********************************************************************************
13 *********************** IO::Network::InternetAddress ***************************
14 ********************************************************************************
15 */
17 : fAddressFamily_{AddressFamily::UNKNOWN}
18 , fV4_{}
19 {
20 }
22 : fAddressFamily_ (AddressFamily::V4)
23#if qStroika_Foundation_Common_Platform_POSIX
24 , fV4_{i}
25#elif qStroika_Foundation_Common_Platform_Windows
26 , fV4_{in_addr{{static_cast<uint8_t> (Memory::BitSubstring (i, 0, 8)), static_cast<uint8_t> (Memory::BitSubstring (i, 8, 16)),
27 static_cast<uint8_t> (Memory::BitSubstring (i, 16, 24)), static_cast<uint8_t> (Memory::BitSubstring (i, 24, 32))}}}
28#endif
29 {
30#if qStroika_Foundation_Common_Platform_Windows
31 Assert (fV4_.s_addr == i);
32#endif
33 }
34 inline InternetAddress::InternetAddress (const in_addr_t& i, ByteOrder byteOrder)
35 : fAddressFamily_{AddressFamily::V4}
36#if qStroika_Foundation_Common_Platform_POSIX
37 , fV4_{i}
38#endif
39 {
40#if qStroika_Foundation_Common_Platform_Windows
41 fV4_.s_addr = i;
42#endif
43 if (byteOrder == ByteOrder::Host) {
44 fV4_.s_addr = htonl (fV4_.s_addr); //NB no ':' cuz some systems use macro
45 }
46 }
47 inline constexpr InternetAddress::InternetAddress (const in_addr& i)
48 : fAddressFamily_{AddressFamily::V4}
49 , fV4_{i}
50 {
51 }
52 inline InternetAddress::InternetAddress (const in_addr& i, ByteOrder byteOrder)
53 : fAddressFamily_{AddressFamily::V4}
54 , fV4_{i}
55 {
56 if (byteOrder == ByteOrder::Host) {
57 fV4_.s_addr = htonl (fV4_.s_addr); //NB no ':' cuz some systems use macro
58 }
59 }
60 constexpr InternetAddress::InternetAddress (byte octet1, byte octet2, byte octet3, byte octet4)
61 : InternetAddress{array<byte, 4>{octet1, octet2, octet3, octet4}}
62 {
63 }
64 constexpr InternetAddress::InternetAddress (uint8_t octet1, uint8_t octet2, uint8_t octet3, uint8_t octet4)
65 : InternetAddress{array<uint8_t, 4>{octet1, octet2, octet3, octet4}}
66 {
67 }
68 constexpr InternetAddress::InternetAddress (array<uint8_t, 4> octets, AddressFamily af)
69 : fAddressFamily_{af}
70 , fArray_4_uint_{octets}
71 {
72 }
73 constexpr InternetAddress::InternetAddress (array<byte, 4> octets, AddressFamily af)
74 : fAddressFamily_{af}
75 , fArray_4_byte_{octets}
76 {
77 }
78 constexpr InternetAddress::InternetAddress (const in6_addr& i)
79 : fAddressFamily_{AddressFamily::V6}
80 , fV6_{i}
81 {
82 }
83 constexpr InternetAddress::InternetAddress (array<uint8_t, 16> octets, AddressFamily af)
84 : fAddressFamily_{af}
85 , fArray_16_uint_{octets}
86 {
87 }
88 constexpr InternetAddress::InternetAddress (array<byte, 16> octets, AddressFamily af)
89 : fAddressFamily_{af}
90 , fArray_16_byte_{octets}
91 {
92 }
93 template <ranges::range ITERABLE_OF_UINT8OrByte>
94 inline InternetAddress::InternetAddress (ITERABLE_OF_UINT8OrByte octets, AddressFamily af)
95 requires (Traversal::IIterableOfTo<ITERABLE_OF_UINT8OrByte, byte> or Traversal::IIterableOfTo<ITERABLE_OF_UINT8OrByte, uint8_t>)
96 : fAddressFamily_{af}
97 {
98 Require (af != AddressFamily::V4 or octets.size () == 4);
99 Require (af != AddressFamily::V6 or octets.size () == 16);
100 size_t i = 0;
101 for (auto b : octets) {
102 fArray_16_uint_[i++] = static_cast<uint8_t> (b);
103 }
104 }
105 constexpr bool InternetAddress::empty () const
106 {
107 return fAddressFamily_ == AddressFamily::UNKNOWN;
108 }
110 {
111 fAddressFamily_ = AddressFamily::UNKNOWN;
112 }
114 {
115 return fAddressFamily_;
116 }
117 constexpr optional<size_t> InternetAddress::GetAddressSize () const
118 {
119 switch (GetAddressFamily ()) {
120 case AddressFamily::V4:
121 return 4;
122 case AddressFamily::V6:
123 return 16;
124 default:
125 return nullopt;
126 }
127 }
129 {
130 return InternetAddress{};
131 }
133 {
134 // @todo - consider if this is really the max (could have longer address at some point in the future - IPV8, 9, 10??)
135 return InternetAddress{array<uint8_t, 16>{
136 0xff,
137 0xff,
138 0xff,
139 0xff,
140 0xff,
141 0xff,
142 0xff,
143 0xff,
144 0xff,
145 0xff,
146 0xff,
147 0xff,
148 0xff,
149 0xff,
150 0xff,
151 0xff,
152 }};
153 }
154 template <>
155 String InternetAddress::As<String> () const;
156#if qStroika_Foundation_Common_Platform_POSIX
157 template <>
158 inline in_addr_t InternetAddress::As<in_addr_t> () const
159 {
160 Require (fAddressFamily_ == AddressFamily::V4);
161 return fV4_.s_addr;
162 }
163#endif
164 template <>
165 constexpr in_addr InternetAddress::As<in_addr> () const
166 {
167 Require (fAddressFamily_ == AddressFamily::V4);
168 return fV4_;
169 }
170 template <>
171 constexpr array<uint8_t, 4> InternetAddress::As<array<uint8_t, 4>> () const
172 {
173 Require (GetAddressSize () == 4u);
174 return fArray_4_uint_;
175 }
176 template <>
177 constexpr array<byte, 4> InternetAddress::As<array<byte, 4>> () const
178 {
179 Require (GetAddressSize () == 4u);
180 return fArray_4_byte_;
181 }
182 template <>
183 constexpr array<uint8_t, 16> InternetAddress::As<array<uint8_t, 16>> () const
184 {
185 Require (GetAddressSize () == 16u);
186 return fArray_16_uint_;
187 }
188 template <>
189 constexpr array<byte, 16> InternetAddress::As<array<byte, 16>> () const
190 {
191 Require (GetAddressSize () == 16u);
192 return fArray_16_byte_;
193 }
194 template <>
195 inline vector<byte> InternetAddress::As<vector<byte>> () const
196 {
197 if (GetAddressSize ().has_value ()) {
198 Assert (*GetAddressSize () <= 16);
199 return vector<byte>{fArray_16_byte_.begin (), fArray_16_byte_.begin () + *GetAddressSize ()};
200 }
201 else {
202 return vector<byte>{};
203 }
204 }
205 template <>
206 inline vector<uint8_t> InternetAddress::As<vector<uint8_t>> () const
207 {
208 if (GetAddressSize ().has_value ()) {
209 Assert (*GetAddressSize () <= 16);
210 return vector<uint8_t>{fArray_16_uint_.begin (), fArray_16_uint_.begin () + *GetAddressSize ()};
211 }
212 else {
213 return vector<uint8_t>{};
214 }
215 }
216 template <>
217 constexpr in6_addr InternetAddress::As<in6_addr> () const
218 {
219 Require (fAddressFamily_ == AddressFamily::V6);
220 return fV6_;
221 }
222 template <>
223 inline in_addr InternetAddress::As<in_addr> (ByteOrder byteOrder) const
224 {
225 Require (fAddressFamily_ == AddressFamily::V4);
226 if (byteOrder == ByteOrder::Network) {
227 return fV4_;
228 }
229 else {
230 in_addr tmp = fV4_;
231 tmp.s_addr = ntohl (tmp.s_addr);
232 return tmp;
233 }
234 }
235 inline strong_ordering InternetAddress::operator<=> (const InternetAddress& rhs) const
236 {
237 return TWC_ (*this, rhs);
238 }
239 inline bool InternetAddress::operator== (const InternetAddress& rhs) const
240 {
241 return TWC_ (*this, rhs) == 0;
242 }
243 inline strong_ordering InternetAddress::TWC_ (const InternetAddress& lhs, const InternetAddress& rhs)
244 {
245 if (auto cmp = lhs.fAddressFamily_ <=> rhs.fAddressFamily_; cmp != strong_ordering::equal) {
246 return cmp;
247 }
248 switch (lhs.fAddressFamily_) {
249 case AddressFamily::UNKNOWN: {
250 return strong_ordering::equal;
251 } break;
252 case AddressFamily::V4: {
253 return Memory::CompareBytes (Traversal::Iterator2Pointer (lhs.fArray_4_uint_.begin ()),
254 Traversal::Iterator2Pointer (rhs.fArray_4_uint_.begin ()), 4) <=> 0;
255 } break;
256 case AddressFamily::V6: {
257 return Memory::CompareBytes (Traversal::Iterator2Pointer (lhs.fArray_16_uint_.begin ()),
258 Traversal::Iterator2Pointer (rhs.fArray_16_uint_.begin ()), 16) <=> 0;
259 } break;
260 }
261 //AssertNotReached (); @todo - this really should be an assertion failure, but tricky cuz constexpr function could fix with template)
262 return strong_ordering::equal;
263 }
264
265 namespace V4 {
266 constexpr InternetAddress kAddrAny{in_addr{}};
267 }
268 namespace V6 {
269 constexpr InternetAddress kAddrAny{in6_addr{}};
270 }
271 namespace V4 {
272 constexpr InternetAddress kLocalhost{0x7f, 0x0, 0x0, 0x1};
273 }
274 namespace V6 {
275 constexpr InternetAddress kLocalhost{in6_addr{{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}}};
276 }
277 namespace V6 {
278 constexpr InternetAddress kV4MappedLocalhost{in6_addr{{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x7f, 0, 0, 1}}}};
279 }
280
281}
282
284
285 inline IO::Network::InternetAddress Default<IO::Network::InternetAddress>::GetNext (IO::Network::InternetAddress n)
286 {
287 Require (n != kUpperBound);
288 return n.Offset (1);
289 }
290 inline IO::Network::InternetAddress Default<IO::Network::InternetAddress>::GetPrevious (IO::Network::InternetAddress n [[maybe_unused]])
291 {
292 Require (n != kLowerBound);
294 return kLowerBound;
295 //return n.Offset (-1); // must fix InternetAddress::Offset to support signed offsets
296 }
297 constexpr auto Default<IO::Network::InternetAddress>::Difference (Common::ArgByValueType<value_type> lhs,
298 Common::ArgByValueType<value_type> rhs) -> SignedDifferenceType
299 {
300 using IO::Network::InternetAddress;
301 Require (lhs.GetAddressFamily () == InternetAddress::AddressFamily::V4);
302 Require (rhs.GetAddressFamily () == InternetAddress::AddressFamily::V4); // because otherwise we need bignums to track difference
303 array<uint8_t, 4> l = lhs.As<array<uint8_t, 4>> ();
304 array<uint8_t, 4> r = rhs.As<array<uint8_t, 4>> ();
305 return (SignedDifferenceType (r[0]) - SignedDifferenceType (l[0])) * (1 << 24) +
306 (SignedDifferenceType (r[1]) - SignedDifferenceType (l[1])) * (1 << 16) +
307 (SignedDifferenceType (r[2]) - SignedDifferenceType (l[2])) * (1 << 8) +
308 (SignedDifferenceType (r[3]) - SignedDifferenceType (l[3])) * (1 << 0);
309 }
310 inline constexpr IO::Network::InternetAddress Default<IO::Network::InternetAddress>::kLowerBound = IO::Network::InternetAddress::min ();
311 inline constexpr IO::Network::InternetAddress Default<IO::Network::InternetAddress>::kUpperBound = IO::Network::InternetAddress::max ();
312
313}
#define AssertNotImplemented()
Definition Assertions.h:401
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
nonvirtual constexpr optional< size_t > GetAddressSize() const
nonvirtual constexpr AddressFamily GetAddressFamily() const