]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/include/experimental/internet
libstdc++: Include scope ID in net::internet::address_v6::to_string()
[thirdparty/gcc.git] / libstdc++-v3 / include / experimental / internet
1 // <experimental/internet> -*- C++ -*-
2
3 // Copyright (C) 2015-2021 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
24
25 /** @file experimental/internet
26 * This is a TS C++ Library header.
27 * @ingroup networking-ts
28 */
29
30 #ifndef _GLIBCXX_EXPERIMENTAL_INTERNET
31 #define _GLIBCXX_EXPERIMENTAL_INTERNET
32
33 #pragma GCC system_header
34
35 #if __cplusplus >= 201402L
36
37 #include <experimental/netfwd>
38 #include <experimental/io_context>
39 #include <experimental/bits/net.h>
40 #include <array>
41 #include <forward_list>
42 #include <sstream>
43 #include <cstdint>
44 #include <experimental/string_view>
45 #ifdef _GLIBCXX_HAVE_UNISTD_H
46 # include <unistd.h>
47 #endif
48 #ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
49 # include <sys/socket.h> // AF_INET, AF_INET6, SOCK_DGRAM, SOCK_STREAM
50 #endif
51 #ifdef _GLIBCXX_HAVE_ARPA_INET_H
52 # include <arpa/inet.h> // inet_ntop
53 #endif
54 #ifdef _GLIBCXX_HAVE_NETINET_IN_H
55 # include <netinet/in.h> // IPPROTO_IP
56 #endif
57 #ifdef _GLIBCXX_HAVE_NETINET_TCP_H
58 # include <netinet/tcp.h> // TCP_NODELAY
59 #endif
60 #ifdef _GLIBCXX_HAVE_NETDB_H
61 # include <netdb.h> // getaddrinfo etc.
62 #endif
63
64 namespace std _GLIBCXX_VISIBILITY(default)
65 {
66 _GLIBCXX_BEGIN_NAMESPACE_VERSION
67 namespace experimental
68 {
69 namespace net
70 {
71 inline namespace v1
72 {
73 namespace ip
74 {
75
76 /** @addtogroup networking-ts
77 * @{
78 */
79
80 #ifdef _GLIBCXX_HAVE_NETDB_H
81 /** Error codes for resolver errors.
82 * @{
83 */
84
85 enum class resolver_errc : int {
86 host_not_found = EAI_NONAME,
87 host_not_found_try_again = EAI_AGAIN,
88 service_not_found = EAI_SERVICE
89 };
90
91 /// Error category for resolver errors.
92 inline const error_category& resolver_category() noexcept // TODO non-inline
93 {
94 struct __cat : error_category
95 {
96 const char* name() const noexcept { return "resolver"; }
97 std::string message(int __e) const { return ::gai_strerror(__e); }
98 virtual void __message(int) { } // TODO dual ABI XXX
99 };
100 static __cat __c;
101 return __c;
102 }
103
104 error_code make_error_code(resolver_errc __e) noexcept
105 { return error_code(static_cast<int>(__e), resolver_category()); }
106
107 error_condition make_error_condition(resolver_errc __e) noexcept
108 { return error_condition(static_cast<int>(__e), resolver_category()); }
109
110 /// @}
111 #endif
112
113 using port_type = uint_least16_t; ///< Type used for port numbers.
114 using scope_id_type = uint_least32_t; ///< Type used for IPv6 scope IDs.
115
116 /// Convenience alias for constraining allocators for strings.
117 template<typename _Alloc>
118 using __string_with
119 = enable_if_t<std::is_same<typename _Alloc::value_type, char>::value,
120 std::basic_string<char, std::char_traits<char>, _Alloc>>;
121
122 /** Tag indicating conversion between IPv4 and IPv4-mapped IPv6 addresses.
123 * @{
124 */
125
126 struct v4_mapped_t {};
127 constexpr v4_mapped_t v4_mapped;
128
129 // @}
130
131 /// An IPv4 address.
132 class address_v4
133 {
134 public:
135 // types:
136 using uint_type = uint_least32_t;
137
138 struct bytes_type : array<unsigned char, 4>
139 {
140 template<typename... _Tp>
141 explicit constexpr
142 bytes_type(_Tp... __tp)
143 : array<unsigned char, 4>{{static_cast<unsigned char>(__tp)...}}
144 {
145 #if UCHAR_MAX > 0xFF
146 for (auto __b : *this)
147 if (__b > 0xFF)
148 __throw_out_of_range("invalid address_v4::bytes_type value");
149 #endif
150 }
151 };
152
153 // constructors:
154 constexpr address_v4() noexcept : _M_addr(0) { }
155
156 constexpr address_v4(const address_v4& a) noexcept = default;
157
158 constexpr
159 address_v4(const bytes_type& __b)
160 : _M_addr((__b[0] << 24) | (__b[1] << 16) | (__b[2] << 8) | __b[3])
161 { }
162
163 explicit constexpr
164 address_v4(uint_type __val) : _M_addr(_S_hton_32(__val))
165 {
166 #if UINT_LEAST32_MAX > 0xFFFFFFFF
167 if (__val > 0xFFFFFFFF)
168 __throw_out_of_range("invalid address_v4::uint_type value");
169 #endif
170 }
171
172 // assignment:
173 address_v4& operator=(const address_v4& a) noexcept = default;
174
175 // members:
176 constexpr bool is_unspecified() const noexcept { return to_uint() == 0; }
177
178 constexpr bool
179 is_loopback() const noexcept
180 { return (to_uint() & 0xFF000000) == 0x7F000000; }
181
182 constexpr bool
183 is_multicast() const noexcept
184 { return (to_uint() & 0xF0000000) == 0xE0000000; }
185
186 constexpr bytes_type
187 to_bytes() const noexcept
188 {
189 return bytes_type{
190 (_M_addr >> 24) & 0xFF,
191 (_M_addr >> 16) & 0xFF,
192 (_M_addr >> 8) & 0xFF,
193 _M_addr & 0xFF
194 };
195 }
196
197 constexpr uint_type
198 to_uint() const noexcept { return _S_ntoh_32(_M_addr); }
199
200 #ifdef _GLIBCXX_HAVE_ARPA_INET_H
201 template<typename _Allocator = allocator<char>>
202 __string_with<_Allocator>
203 to_string(const _Allocator& __a = _Allocator()) const
204 {
205 __string_with<_Allocator> __str(__a);
206 __str.resize(INET6_ADDRSTRLEN);
207 if (inet_ntop(AF_INET, &_M_addr, &__str.front(), __str.size()))
208 __str.erase(__str.find('\0'));
209 else
210 __str.resize(0);
211 return __str;
212 }
213 #endif
214
215 // static members:
216 static constexpr address_v4 any() noexcept { return address_v4{}; }
217
218 static constexpr
219 address_v4 loopback() noexcept { return address_v4{0x7F000001}; }
220
221 static constexpr
222 address_v4 broadcast() noexcept { return address_v4{0xFFFFFFFF}; }
223
224 private:
225 template<typename _InternetProtocol>
226 friend class basic_endpoint;
227
228 friend address_v4 make_address_v4(const char*, error_code&) noexcept;
229
230 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
231 static constexpr uint16_t _S_hton_16(uint16_t __h) { return __h; }
232 static constexpr uint16_t _S_ntoh_16(uint16_t __n) { return __n; }
233 static constexpr uint32_t _S_hton_32(uint32_t __h) { return __h; }
234 static constexpr uint32_t _S_ntoh_32(uint32_t __n) { return __n; }
235 #else
236 static constexpr uint16_t
237 _S_hton_16(uint16_t __h) { return __builtin_bswap16(__h); }
238
239 static constexpr uint16_t
240 _S_ntoh_16(uint16_t __n) { return __builtin_bswap16(__n); }
241
242 static constexpr uint32_t
243 _S_hton_32(uint32_t __h) { return __builtin_bswap32(__h); }
244
245 static constexpr uint32_t
246 _S_ntoh_32(uint32_t __n) { return __builtin_bswap32(__n); }
247 #endif
248
249 in_addr_t _M_addr; // network byte order
250 };
251
252 /// An IPv6 address.
253 class address_v6
254 {
255 public:
256 // types:
257 struct bytes_type : array<unsigned char, 16>
258 {
259 template<typename... _Tp> explicit constexpr bytes_type(_Tp... __t)
260 : array<unsigned char, 16>{{static_cast<unsigned char>(__t)...}} { }
261 };
262
263 // constructors:
264 constexpr address_v6() noexcept : _M_bytes(), _M_scope_id() { }
265
266 constexpr address_v6(const address_v6& __a) noexcept = default;
267
268 constexpr
269 address_v6(const bytes_type& __bytes, scope_id_type __scope = 0)
270 : _M_bytes(__bytes), _M_scope_id(__scope)
271 { }
272
273 // assignment:
274 address_v6& operator=(const address_v6& __a) noexcept = default;
275
276 // members:
277 void scope_id(scope_id_type __id) noexcept { _M_scope_id = __id; }
278
279 constexpr scope_id_type scope_id() const noexcept { return _M_scope_id; }
280
281 constexpr bool
282 is_unspecified() const noexcept
283 {
284 for (int __i = 0; __i < 16; ++__i)
285 if (_M_bytes[__i] != 0x00)
286 return false;
287 return _M_scope_id == 0;
288 }
289
290 constexpr bool
291 is_loopback() const noexcept
292 {
293 for (int __i = 0; __i < 15; ++__i)
294 if (_M_bytes[__i] != 0x00)
295 return false;
296 return _M_bytes[15] == 0x01 && _M_scope_id == 0;
297 }
298
299 constexpr bool
300 is_multicast() const noexcept { return _M_bytes[0] == 0xFF; }
301
302 constexpr bool
303 is_link_local() const noexcept
304 { return _M_bytes[0] == 0xFE && (_M_bytes[1] & 0xC0) == 0x80; }
305
306 constexpr bool
307 is_site_local() const noexcept
308 { return _M_bytes[0] == 0xFE && (_M_bytes[1] & 0xC0) == 0xC0; }
309
310 constexpr bool
311 is_v4_mapped() const noexcept
312 {
313 const bytes_type& __b = _M_bytes;
314 return __b[0] == 0 && __b[1] == 0 && __b[ 2] == 0 && __b[ 3] == 0
315 && __b[4] == 0 && __b[5] == 0 && __b[ 6] == 0 && __b[ 7] == 0
316 && __b[8] == 0 && __b[9] == 0 && __b[10] == 0xFF && __b[11] == 0xFF;
317 }
318
319 constexpr bool
320 is_multicast_node_local() const noexcept
321 { return is_multicast() && (_M_bytes[1] & 0x0F) == 0x01; }
322
323 constexpr bool
324 is_multicast_link_local() const noexcept
325 { return is_multicast() && (_M_bytes[1] & 0x0F) == 0x02; }
326
327 constexpr bool
328 is_multicast_site_local() const noexcept
329 { return is_multicast() && (_M_bytes[1] & 0x0F) == 0x05; }
330
331 constexpr bool
332 is_multicast_org_local() const noexcept
333 { return is_multicast() && (_M_bytes[1] & 0x0F) == 0x08; }
334
335 constexpr bool
336 is_multicast_global() const noexcept
337 { return is_multicast() && (_M_bytes[1] & 0x0F) == 0x0b; }
338
339 constexpr bytes_type to_bytes() const noexcept { return _M_bytes; }
340
341 #ifdef _GLIBCXX_HAVE_ARPA_INET_H
342 template<typename _Allocator = allocator<char>>
343 __string_with<_Allocator>
344 to_string(const _Allocator& __a = _Allocator()) const
345 {
346 __string_with<_Allocator> __str(__a);
347 __str.resize(INET6_ADDRSTRLEN + (_M_scope_id ? 11 : 0));
348 char* const __p = &__str.front();
349 if (inet_ntop(AF_INET6, &_M_bytes, __p, __str.size()))
350 {
351 auto __end = __str.find('\0');
352 if (unsigned long __scope = _M_scope_id)
353 {
354 __end +=
355 #if _GLIBCXX_USE_C99_STDIO
356 __builtin_snprintf(__p + __end, __str.size() - __end,
357 "%%%lu", __scope);
358 #else
359 __builtin_sprintf(__p + __end, "%%%lu", __scope);
360 #endif
361 }
362 __str.erase(__end);
363 }
364 else
365 __str.resize(0);
366 return __str;
367 }
368 #endif
369
370 // static members:
371
372 static constexpr address_v6
373 any() noexcept
374 {
375 return {};
376 }
377
378 static constexpr address_v6
379 loopback() noexcept
380 {
381 return {bytes_type{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}};
382 }
383
384 private:
385 template<typename _InternetProtocol>
386 friend class basic_endpoint;
387
388 friend constexpr bool
389 operator==(const address_v6&, const address_v6&) noexcept;
390
391 friend constexpr bool
392 operator< (const address_v6&, const address_v6&) noexcept;
393
394 bytes_type _M_bytes;
395 scope_id_type _M_scope_id;
396 };
397
398 /// Exception type thrown on misuse of IPv4 addresses as IPv6 or vice versa.
399 class bad_address_cast : public bad_cast
400 {
401 public:
402 bad_address_cast() { }
403
404 const char* what() const noexcept { return "bad address cast"; }
405 };
406
407 /// An IPv4 or IPv6 address.
408 class address
409 {
410 public:
411 // constructors:
412 constexpr address() noexcept : _M_v4(), _M_is_v4(true) { }
413
414 constexpr
415 address(const address& __a) noexcept : _M_uninit(), _M_is_v4(__a._M_is_v4)
416 {
417 if (_M_is_v4)
418 ::new (std::addressof(_M_v4)) address_v4(__a.to_v4());
419 else
420 ::new (std::addressof(_M_v6)) address_v6(__a.to_v6());
421 }
422
423 constexpr
424 address(const address_v4& __a) noexcept : _M_v4(__a), _M_is_v4(true) { }
425
426 constexpr
427 address(const address_v6& __a) noexcept : _M_v6(__a), _M_is_v4(false) { }
428
429 // assignment:
430 address&
431 operator=(const address& __a) noexcept
432 {
433 if (__a._M_is_v4)
434 *this = __a.to_v4();
435 else
436 *this = __a.to_v6();
437 return *this;
438 }
439
440 address&
441 operator=(const address_v4& __a) noexcept
442 {
443 ::new (std::addressof(_M_v4)) address_v4(__a);
444 _M_is_v4 = true;
445 return *this;
446 }
447
448 address&
449 operator=(const address_v6& __a) noexcept
450 {
451 ::new (std::addressof(_M_v6)) address_v6(__a);
452 _M_is_v4 = false;
453 return *this;
454 }
455
456 // members:
457
458 constexpr bool is_v4() const noexcept { return _M_is_v4; }
459 constexpr bool is_v6() const noexcept { return !_M_is_v4; }
460
461 constexpr address_v4
462 to_v4() const
463 {
464 if (!is_v4())
465 _GLIBCXX_THROW_OR_ABORT(bad_address_cast());
466 return _M_v4;
467 }
468
469 constexpr address_v6
470 to_v6() const
471 {
472 if (!is_v6())
473 _GLIBCXX_THROW_OR_ABORT(bad_address_cast());
474 return _M_v6;
475 }
476
477 constexpr bool
478 is_unspecified() const noexcept
479 { return _M_is_v4 ? _M_v4.is_unspecified() : _M_v6.is_unspecified(); }
480
481 constexpr bool
482 is_loopback() const noexcept
483 { return _M_is_v4 ? _M_v4.is_loopback() : _M_v6.is_loopback(); }
484
485 constexpr bool
486 is_multicast() const noexcept
487 { return _M_is_v4 ? _M_v4.is_multicast() : _M_v6.is_multicast(); }
488
489 template<typename _Allocator = allocator<char>>
490 __string_with<_Allocator>
491 to_string(const _Allocator& __a = _Allocator()) const
492 {
493 if (_M_is_v4)
494 return to_v4().to_string(__a);
495 return to_v6().to_string(__a);
496 }
497
498 private:
499 template<typename _InternetProtocol>
500 friend class basic_endpoint;
501
502 friend constexpr bool
503 operator==(const address&, const address&) noexcept;
504
505 friend constexpr bool
506 operator<(const address&, const address&) noexcept;
507
508 union {
509 address_v4 _M_v4;
510 address_v6 _M_v6;
511 bool _M_uninit;
512 };
513 bool _M_is_v4;
514 };
515
516 /** ip::address_v4 comparisons
517 * @{
518 */
519
520 constexpr bool
521 operator==(const address_v4& __a, const address_v4& __b) noexcept
522 { return __a.to_uint() == __b.to_uint(); }
523
524 constexpr bool
525 operator!=(const address_v4& __a, const address_v4& __b) noexcept
526 { return !(__a == __b); }
527
528 constexpr bool
529 operator< (const address_v4& __a, const address_v4& __b) noexcept
530 { return __a.to_uint() < __b.to_uint(); }
531
532 constexpr bool
533 operator> (const address_v4& __a, const address_v4& __b) noexcept
534 { return __b < __a; }
535
536 constexpr bool
537 operator<=(const address_v4& __a, const address_v4& __b) noexcept
538 { return !(__b < __a); }
539
540 constexpr bool
541 operator>=(const address_v4& __a, const address_v4& __b) noexcept
542 { return !(__a < __b); }
543
544 // @}
545
546 /** ip::address_v6 comparisons
547 * @{
548 */
549
550 constexpr bool
551 operator==(const address_v6& __a, const address_v6& __b) noexcept
552 {
553 const auto& __aa = __a._M_bytes;
554 const auto& __bb = __b._M_bytes;
555 int __i = 0;
556 for (; __i < 16 && __aa[__i] == __bb[__i]; ++__i)
557 ;
558 return __i == 16 ? __a.scope_id() == __b.scope_id() : false;
559 }
560
561 constexpr bool
562 operator!=(const address_v6& __a, const address_v6& __b) noexcept
563 { return !(__a == __b); }
564
565 constexpr bool
566 operator< (const address_v6& __a, const address_v6& __b) noexcept
567 {
568 const auto& __aa = __a._M_bytes;
569 const auto& __bb = __b._M_bytes;
570 int __i = 0;
571 for (; __i < 16 && __aa[__i] == __bb[__i]; ++__i)
572 ;
573 return __i == 16 ? __a.scope_id() < __b.scope_id() : __aa[__i] < __bb[__i];
574 }
575
576 constexpr bool
577 operator> (const address_v6& __a, const address_v6& __b) noexcept
578 { return __b < __a; }
579
580 constexpr bool
581 operator<=(const address_v6& __a, const address_v6& __b) noexcept
582 { return !(__b < __a); }
583
584 constexpr bool
585 operator>=(const address_v6& __a, const address_v6& __b) noexcept
586 { return !(__a < __b); }
587
588 // @}
589
590 /** ip::address comparisons
591 * @{
592 */
593
594 constexpr bool
595 operator==(const address& __a, const address& __b) noexcept
596 {
597 if (__a.is_v4())
598 return __b.is_v4() ? __a._M_v4 == __b._M_v4 : false;
599 return __b.is_v4() ? false : __a._M_v6 == __b._M_v6;
600 }
601
602 constexpr bool
603 operator!=(const address& __a, const address& __b) noexcept
604 { return !(__a == __b); }
605
606 constexpr bool
607 operator< (const address& __a, const address& __b) noexcept
608 {
609 if (__a.is_v4())
610 return __b.is_v4() ? __a._M_v4 < __b._M_v4 : true;
611 return __b.is_v4() ? false : __a._M_v6 < __b._M_v6;
612 }
613
614 constexpr bool
615 operator> (const address& __a, const address& __b) noexcept
616 { return __b < __a; }
617
618 constexpr bool
619 operator<=(const address& __a, const address& __b) noexcept
620 { return !(__b < __a); }
621
622 constexpr bool
623 operator>=(const address& __a, const address& __b) noexcept
624 { return !(__a < __b); }
625
626 // @}
627
628 /** ip::address_v4 creation
629 * @{
630 */
631
632 constexpr address_v4
633 make_address_v4(const address_v4::bytes_type& __b)
634 { return address_v4{__b}; }
635
636 constexpr address_v4
637 make_address_v4(address_v4::uint_type __val)
638 { return address_v4{__val}; }
639
640 constexpr address_v4
641 make_address_v4(v4_mapped_t, const address_v6& __a)
642 {
643 if (!__a.is_v4_mapped())
644 _GLIBCXX_THROW_OR_ABORT(bad_address_cast());
645
646 const auto __v6b = __a.to_bytes();
647 return address_v4::bytes_type(__v6b[12], __v6b[13], __v6b[14], __v6b[15]);
648 }
649
650 inline address_v4
651 make_address_v4(const char* __str, error_code& __ec) noexcept
652 {
653 address_v4 __a;
654 const int __res = ::inet_pton(AF_INET, __str, &__a._M_addr);
655 if (__res == 1)
656 {
657 __ec.clear();
658 return __a;
659 }
660 if (__res == 0)
661 __ec = std::make_error_code(std::errc::invalid_argument);
662 else
663 __ec.assign(errno, generic_category());
664 return {};
665 }
666
667 inline address_v4
668 make_address_v4(const char* __str)
669 { return make_address_v4(__str, __throw_on_error{"make_address_v4"}); }
670
671 inline address_v4
672 make_address_v4(const string& __str, error_code& __ec) noexcept
673 { return make_address_v4(__str.c_str(), __ec); }
674
675 inline address_v4
676 make_address_v4(const string& __str)
677 { return make_address_v4(__str.c_str()); }
678
679 inline address_v4
680 make_address_v4(string_view __str, error_code& __ec) noexcept
681 {
682 char __buf[INET_ADDRSTRLEN];
683 auto __len = __str.copy(__buf, sizeof(__buf));
684 if (__len == sizeof(__buf))
685 {
686 __ec = std::make_error_code(std::errc::invalid_argument);
687 return {};
688 }
689 __ec.clear();
690 __buf[__len] = '\0';
691 return make_address_v4(__buf, __ec);
692 }
693
694 inline address_v4
695 make_address_v4(string_view __str)
696 { return make_address_v4(__str, __throw_on_error{"make_address_v4"}); }
697
698 // @}
699
700 /** ip::address_v6 creation
701 * @{
702 */
703
704 constexpr address_v6
705 make_address_v6(const address_v6::bytes_type& __b, scope_id_type __scope = 0)
706 { return address_v6{__b, __scope}; }
707
708 constexpr address_v6
709 make_address_v6(v4_mapped_t, const address_v4& __a) noexcept
710 {
711 const address_v4::bytes_type __v4b = __a.to_bytes();
712 address_v6::bytes_type __v6b(0, 0, 0, 0, 0, 0, 0, 0,
713 0, 0, 0xFF, 0xFF,
714 __v4b[0], __v4b[1], __v4b[2], __v4b[3]);
715 return address_v6(__v6b);
716 }
717
718 inline address_v6
719 __make_address_v6(const char* __addr, const char* __scope, error_code& __ec)
720 {
721 address_v6::bytes_type __b;
722 int __res = ::inet_pton(AF_INET6, __addr, __b.data());
723 if (__res == 1)
724 {
725 __ec.clear();
726 if (!__scope)
727 {
728 return { __b };
729 }
730
731 char* __eptr;
732 unsigned long __val = std::strtoul(__scope, &__eptr, 10);
733 if (__eptr != __scope && !*__eptr
734 && __val <= numeric_limits<scope_id_type>::max())
735 {
736 return { __b, static_cast<scope_id_type>(__val) };
737 }
738 __ec = std::make_error_code(std::errc::invalid_argument);
739 }
740 else if (__res == 0)
741 __ec = std::make_error_code(std::errc::invalid_argument);
742 else
743 __ec.assign(errno, generic_category());
744 return {};
745 }
746
747 inline address_v6
748 make_address_v6(const char* __str, error_code& __ec) noexcept
749 {
750 auto __p = __builtin_strchr(__str, '%');
751 if (__p == nullptr)
752 return __make_address_v6(__str, nullptr, __ec);
753 char __buf[64];
754 char* __out = __buf;
755 bool __skip_leading_zero = true;
756 while (__str < __p && __out < std::end(__buf))
757 {
758 if (!__skip_leading_zero || *__str != '0')
759 {
760 if (*__str == ':' || *__str == '.')
761 __skip_leading_zero = true;
762 else
763 __skip_leading_zero = false;
764 *__out = *__str;
765 }
766 __str++;
767 }
768 if (__out == std::end(__buf))
769 {
770 __ec = std::make_error_code(std::errc::invalid_argument);
771 return {};
772 }
773 else
774 {
775 *__out = '\0';
776 return __make_address_v6(__buf, __p + 1, __ec);
777 }
778 }
779
780 inline address_v6
781 make_address_v6(const char* __str)
782 { return make_address_v6(__str, __throw_on_error{"make_address_v6"}); }
783
784 inline address_v6
785 make_address_v6(const string& __str, error_code& __ec) noexcept
786 {
787 auto __pos = __str.find('%');
788 if (__pos == string::npos)
789 return __make_address_v6(__str.c_str(), nullptr, __ec);
790 char __buf[64];
791 char* __out = __buf;
792 bool __skip_leading_zero = true;
793 size_t __n = 0;
794 while (__n < __pos && __out < std::end(__buf))
795 {
796 if (!__skip_leading_zero || __str[__n] != '0')
797 {
798 if (__str[__n] == ':' || __str[__n] == '.')
799 __skip_leading_zero = true;
800 else
801 __skip_leading_zero = false;
802 *__out = __str[__n];
803 }
804 __n++;
805 }
806 if (__out == std::end(__buf))
807 {
808 __ec = std::make_error_code(std::errc::invalid_argument);
809 return {};
810 }
811 else
812 {
813 *__out = '\0';
814 return __make_address_v6(__buf, __str.c_str() + __pos + 1, __ec);
815 }
816 }
817
818 inline address_v6
819 make_address_v6(const string& __str)
820 { return make_address_v6(__str, __throw_on_error{"make_address_v6"}); }
821
822 inline address_v6
823 make_address_v6(string_view __str, error_code& __ec) noexcept
824 {
825 char __buf[64];
826 char* __out = __buf;
827 char* __scope = nullptr;
828 bool __skip_leading_zero = true;
829 size_t __n = 0;
830 while (__n < __str.length() && __out < std::end(__buf))
831 {
832 if (__str[__n] == '%')
833 {
834 if (__scope)
835 __out = std::end(__buf);
836 else
837 {
838 *__out = '\0';
839 __scope = ++__out;
840 __skip_leading_zero = true;
841 }
842 }
843 else if (!__skip_leading_zero || __str[__n] != '0')
844 {
845 if (__str[__n] == ':' || __str[__n] == '.')
846 __skip_leading_zero = true;
847 else
848 __skip_leading_zero = false;
849 *__out = __str[__n];
850 __out++;
851 }
852 __n++;
853 }
854 if (__out == std::end(__buf))
855 {
856 __ec = std::make_error_code(std::errc::invalid_argument);
857 return {};
858 }
859 else
860 {
861 *__out = '\0';
862 return __make_address_v6(__buf, __scope, __ec);
863 }
864 }
865
866 inline address_v6
867 make_address_v6(string_view __str)
868 { return make_address_v6(__str, __throw_on_error{"make_address_v6"}); }
869
870 // @}
871
872 /** ip::address creation
873 * @{
874 */
875
876 inline address
877 make_address(const char* __str, error_code& __ec) noexcept
878 {
879 address __a;
880 address_v6 __v6a = make_address_v6(__str, __ec);
881 if (!__ec)
882 __a = __v6a;
883 else
884 {
885 address_v4 __v4a = make_address_v4(__str, __ec);
886 if (!__ec)
887 __a = __v4a;
888 }
889 return __a;
890 }
891
892 inline address
893 make_address(const char* __str)
894 { return make_address(__str, __throw_on_error{"make_address"}); }
895
896 inline address
897 make_address(const string& __str, error_code& __ec) noexcept; // TODO
898
899 inline address
900 make_address(const string& __str)
901 { return make_address(__str, __throw_on_error{"make_address"}); }
902
903 inline address
904 make_address(string_view __str, error_code& __ec) noexcept
905 {
906 if (__str.rfind('\0') != string_view::npos)
907 return make_address(__str.data(), __ec);
908 return make_address(__str.to_string(), __ec); // TODO don't allocate
909 }
910
911 inline address
912 make_address(string_view __str)
913 { return make_address(__str, __throw_on_error{"make_address"}); }
914
915 // @}
916
917 /// ip::address I/O
918 template<typename _CharT, typename _Traits>
919 inline basic_ostream<_CharT, _Traits>&
920 operator<<(basic_ostream<_CharT, _Traits>& __os, const address& __a)
921 { return __os << __a.to_string(); }
922
923 /// ip::address_v4 I/O
924 template<typename _CharT, typename _Traits>
925 inline basic_ostream<_CharT, _Traits>&
926 operator<<(basic_ostream<_CharT, _Traits>& __os, const address_v4& __a)
927 { return __os << __a.to_string(); }
928
929 /// ip::address_v6 I/O
930 template<typename _CharT, typename _Traits>
931 inline basic_ostream<_CharT, _Traits>&
932 operator<<(basic_ostream<_CharT, _Traits>& __os, const address_v6& __a)
933 { return __os << __a.to_string(); }
934
935 template<typename> class basic_address_iterator; // not defined
936
937 template<> class basic_address_iterator<address_v4>
938 {
939 public:
940 // types:
941 using value_type = address_v4;
942 using difference_type = ptrdiff_t;
943 using pointer = const address_v4*;
944 using reference = const address_v4&;
945 using iterator_category = input_iterator_tag;
946
947 // constructors:
948 basic_address_iterator(const address_v4& __a) noexcept
949 : _M_address(__a) { }
950
951 // members:
952 reference operator*() const noexcept { return _M_address; }
953 pointer operator->() const noexcept { return &_M_address; }
954
955 basic_address_iterator&
956 operator++() noexcept
957 {
958 _M_address = value_type(_M_address.to_uint() + 1);
959 return *this;
960 }
961
962 basic_address_iterator operator++(int) noexcept
963 {
964 auto __tmp = *this;
965 ++*this;
966 return __tmp;
967 }
968
969 basic_address_iterator& operator--() noexcept
970 {
971 _M_address = value_type(_M_address.to_uint() - 1);
972 return *this;
973 }
974
975 basic_address_iterator
976 operator--(int) noexcept
977 {
978 auto __tmp = *this;
979 --*this;
980 return __tmp;
981 }
982
983 bool
984 operator==(const basic_address_iterator& __rhs) const noexcept
985 { return _M_address == __rhs._M_address; }
986
987 bool
988 operator!=(const basic_address_iterator& __rhs) const noexcept
989 { return _M_address != __rhs._M_address; }
990
991 private:
992 address_v4 _M_address;
993 };
994
995 using address_v4_iterator = basic_address_iterator<address_v4>;
996
997 template<> class basic_address_iterator<address_v6>
998 {
999 public:
1000 // types:
1001 using value_type = address_v6;
1002 using difference_type = ptrdiff_t;
1003 using pointer = const address_v6*;
1004 using reference = const address_v6&;
1005 using iterator_category = input_iterator_tag;
1006
1007 // constructors:
1008 basic_address_iterator(const address_v6& __a) noexcept
1009 : _M_address(__a) { }
1010
1011 // members:
1012 reference operator*() const noexcept { return _M_address; }
1013 pointer operator->() const noexcept { return &_M_address; }
1014
1015 basic_address_iterator&
1016 operator++() noexcept; // TODO
1017
1018 basic_address_iterator
1019 operator++(int) noexcept
1020 {
1021 auto __tmp = *this;
1022 ++*this;
1023 return __tmp;
1024 }
1025
1026 basic_address_iterator&
1027 operator--() noexcept; // TODO
1028
1029 basic_address_iterator
1030 operator--(int) noexcept
1031 {
1032 auto __tmp = *this;
1033 --*this;
1034 return __tmp;
1035 }
1036
1037 bool
1038 operator==(const basic_address_iterator& __rhs) const noexcept
1039 { return _M_address == __rhs._M_address; }
1040
1041 bool
1042 operator!=(const basic_address_iterator& __rhs) const noexcept
1043 { return _M_address != __rhs._M_address; }
1044
1045 private:
1046 address_v6 _M_address;
1047 };
1048
1049 using address_v6_iterator = basic_address_iterator<address_v6>;
1050
1051 template<typename> class basic_address_range; // not defined
1052
1053 /** An IPv6 address range.
1054 * @{
1055 */
1056
1057 template<> class basic_address_range<address_v4>
1058 {
1059 public:
1060 // types:
1061
1062 using iterator = basic_address_iterator<address_v4>;
1063
1064 // constructors:
1065
1066 basic_address_range() noexcept : _M_begin({}), _M_end({}) { }
1067
1068 basic_address_range(const address_v4& __first,
1069 const address_v4& __last) noexcept
1070 : _M_begin(__first), _M_end(__last) { }
1071
1072 // members:
1073
1074 iterator begin() const noexcept { return _M_begin; }
1075 iterator end() const noexcept { return _M_end; }
1076 _GLIBCXX_NODISCARD bool empty() const noexcept { return _M_begin == _M_end; }
1077
1078 size_t
1079 size() const noexcept { return _M_end->to_uint() - _M_begin->to_uint(); }
1080
1081 iterator
1082 find(const address_v4& __addr) const noexcept
1083 {
1084 if (*_M_begin <= __addr && __addr < *_M_end)
1085 return iterator{__addr};
1086 return end();
1087 }
1088
1089 private:
1090 iterator _M_begin;
1091 iterator _M_end;
1092 };
1093
1094 using address_v4_range = basic_address_range<address_v4>;
1095
1096 // @}
1097
1098 /** An IPv6 address range.
1099 * @{
1100 */
1101
1102 template<> class basic_address_range<address_v6>
1103 {
1104 public:
1105 // types:
1106
1107 using iterator = basic_address_iterator<address_v6>;
1108
1109 // constructors:
1110
1111 basic_address_range() noexcept : _M_begin({}), _M_end({}) { }
1112 basic_address_range(const address_v6& __first,
1113 const address_v6& __last) noexcept
1114 : _M_begin(__first), _M_end(__last) { }
1115
1116 // members:
1117
1118 iterator begin() const noexcept { return _M_begin; }
1119 iterator end() const noexcept { return _M_end; }
1120 _GLIBCXX_NODISCARD bool empty() const noexcept { return _M_begin == _M_end; }
1121
1122 iterator
1123 find(const address_v6& __addr) const noexcept
1124 {
1125 if (*_M_begin <= __addr && __addr < *_M_end)
1126 return iterator{__addr};
1127 return end();
1128 }
1129
1130 private:
1131 iterator _M_begin;
1132 iterator _M_end;
1133 };
1134
1135 using address_v6_range = basic_address_range<address_v6>;
1136
1137 // @}
1138
1139 bool
1140 operator==(const network_v4& __a, const network_v4& __b) noexcept;
1141
1142 bool
1143 operator==(const network_v6& __a, const network_v6& __b) noexcept;
1144
1145
1146 /// An IPv4 network address.
1147 class network_v4
1148 {
1149 public:
1150 // constructors:
1151 constexpr network_v4() noexcept : _M_addr(), _M_prefix_len(0) { }
1152
1153 constexpr
1154 network_v4(const address_v4& __addr, int __prefix_len)
1155 : _M_addr(__addr), _M_prefix_len(__prefix_len)
1156 {
1157 if (_M_prefix_len < 0 || _M_prefix_len > 32)
1158 __throw_out_of_range("network_v4: invalid prefix length");
1159 }
1160
1161 constexpr
1162 network_v4(const address_v4& __addr, const address_v4& __mask)
1163 : _M_addr(__addr), _M_prefix_len(__builtin_popcount(__mask.to_uint()))
1164 {
1165 if (_M_prefix_len != 0)
1166 {
1167 address_v4::uint_type __mask_uint = __mask.to_uint();
1168 if (__builtin_ctz(__mask_uint) != (32 - _M_prefix_len))
1169 __throw_invalid_argument("network_v4: invalid mask");
1170 if ((__mask_uint & 0x80000000) == 0)
1171 __throw_invalid_argument("network_v4: invalid mask");
1172 }
1173 }
1174
1175 // members:
1176
1177 constexpr address_v4 address() const noexcept { return _M_addr; }
1178 constexpr int prefix_length() const noexcept { return _M_prefix_len; }
1179
1180 constexpr address_v4
1181 netmask() const noexcept
1182 {
1183 address_v4::uint_type __val = address_v4::broadcast().to_uint();
1184 __val >>= (32 - _M_prefix_len);
1185 __val <<= (32 - _M_prefix_len);
1186 return address_v4{__val};
1187 }
1188
1189 constexpr address_v4
1190 network() const noexcept
1191 { return address_v4{_M_addr.to_uint() & netmask().to_uint()}; }
1192
1193 constexpr address_v4
1194 broadcast() const noexcept
1195 { return address_v4{_M_addr.to_uint() | ~netmask().to_uint()}; }
1196
1197 address_v4_range
1198 hosts() const noexcept
1199 {
1200 if (is_host())
1201 return { address(), *++address_v4_iterator(address()) };
1202 return { network(), broadcast() };
1203 }
1204
1205 constexpr network_v4
1206 canonical() const noexcept
1207 { return network_v4(network(), prefix_length()); }
1208
1209 constexpr bool is_host() const noexcept { return _M_prefix_len == 32; }
1210
1211 constexpr bool
1212 is_subnet_of(const network_v4& __other) const noexcept
1213 {
1214 if (__other.prefix_length() < prefix_length())
1215 {
1216 network_v4 __net(address(), __other.prefix_length());
1217 return __net.canonical() == __other.canonical();
1218 }
1219 return false;
1220 }
1221
1222 template<typename _Allocator = allocator<char>>
1223 __string_with<_Allocator>
1224 to_string(const _Allocator& __a = _Allocator()) const
1225 {
1226 return address().to_string(__a) + '/'
1227 + std::to_string(prefix_length());
1228 }
1229
1230 private:
1231 address_v4 _M_addr;
1232 int _M_prefix_len;
1233 };
1234
1235 /// An IPv6 network address.
1236 class network_v6
1237 {
1238 public:
1239 // constructors:
1240 constexpr network_v6() noexcept : _M_addr(), _M_prefix_len(0) { }
1241
1242 constexpr
1243 network_v6(const address_v6& __addr, int __prefix_len)
1244 : _M_addr(__addr), _M_prefix_len(__prefix_len)
1245 {
1246 if (_M_prefix_len < 0 || _M_prefix_len > 128)
1247 __throw_out_of_range("network_v6: invalid prefix length");
1248 }
1249
1250 // members:
1251 constexpr address_v6 address() const noexcept { return _M_addr; }
1252 constexpr int prefix_length() const noexcept { return _M_prefix_len; }
1253
1254 constexpr address_v6 network() const noexcept; // TODO
1255
1256 address_v6_range
1257 hosts() const noexcept
1258 {
1259 if (is_host())
1260 return { address(), *++address_v6_iterator(address()) };
1261 return {}; // { network(), XXX broadcast() XXX }; // TODO
1262 }
1263
1264 constexpr network_v6
1265 canonical() const noexcept
1266 { return network_v6{network(), prefix_length()}; }
1267
1268 constexpr bool is_host() const noexcept { return _M_prefix_len == 128; }
1269
1270 constexpr bool
1271 is_subnet_of(const network_v6& __other) const noexcept
1272 {
1273 if (__other.prefix_length() < prefix_length())
1274 {
1275 network_v6 __net(address(), __other.prefix_length());
1276 return __net.canonical() == __other.canonical();
1277 }
1278 return false;
1279 }
1280
1281 template<typename _Allocator = allocator<char>>
1282 __string_with<_Allocator>
1283 to_string(const _Allocator& __a = _Allocator()) const
1284 {
1285 return address().to_string(__a) + '/'
1286 + std::to_string(prefix_length());
1287 }
1288
1289 private:
1290 address_v6 _M_addr;
1291 int _M_prefix_len;
1292 };
1293
1294
1295 /** ip::network_v4 comparisons
1296 * @{
1297 */
1298
1299 inline bool
1300 operator==(const network_v4& __a, const network_v4& __b) noexcept
1301 {
1302 return __a.address() == __b.address()
1303 && __a.prefix_length() == __b.prefix_length();
1304 }
1305
1306 inline bool
1307 operator!=(const network_v4& __a, const network_v4& __b) noexcept
1308 { return !(__a == __b); }
1309
1310 // @}
1311
1312 /** ip::network_v6 comparisons
1313 * @{
1314 */
1315
1316 inline bool
1317 operator==(const network_v6& __a, const network_v6& __b) noexcept
1318 {
1319 return __a.address() == __b.address()
1320 && __a.prefix_length() == __b.prefix_length();
1321 }
1322
1323 inline bool
1324 operator!=(const network_v6& __a, const network_v6& __b) noexcept
1325 { return !(__a == __b); }
1326
1327 // @}
1328
1329 /** ip::network_v4 creation
1330 * @{
1331 */
1332
1333 inline network_v4
1334 make_network_v4(const address_v4& __a, int __prefix_len)
1335 { return network_v4{__a, __prefix_len}; }
1336
1337 network_v4
1338 make_network_v4(const address_v4& __a, const address_v4& __mask)
1339 { return network_v4{ __a, __mask }; }
1340
1341 network_v4 make_network_v4(const char*, error_code&) noexcept; // TODO
1342
1343 inline network_v4
1344 make_network_v4(const char* __str)
1345 { return make_network_v4(__str, __throw_on_error{"make_network_v4"}); }
1346
1347 network_v4 make_network_v4(const string&, error_code&) noexcept; // TODO
1348
1349 inline network_v4
1350 make_network_v4(const string& __str)
1351 { return make_network_v4(__str, __throw_on_error{"make_network_v4"}); }
1352
1353 network_v4 make_network_v4(string_view, error_code&) noexcept; // TODO
1354
1355 inline network_v4
1356 make_network_v4(string_view __str)
1357 { return make_network_v4(__str, __throw_on_error{"make_network_v4"}); }
1358
1359 // @}
1360
1361 /** ip::network_v6 creation
1362 * @{
1363 */
1364
1365 inline network_v6
1366 make_network_v6(const address_v6& __a, int __prefix_len)
1367 { return network_v6{__a, __prefix_len}; }
1368
1369 network_v6 make_network_v6(const char*, error_code&) noexcept; // TODO
1370
1371 inline network_v6
1372 make_network_v6(const char* __str)
1373 { return make_network_v6(__str, __throw_on_error{"make_network_v6"}); }
1374
1375 network_v6 make_network_v6(const string&, error_code&) noexcept; // TODO
1376
1377 inline network_v6
1378 make_network_v6(const string& __str)
1379 { return make_network_v6(__str, __throw_on_error{"make_network_v6"}); }
1380
1381 network_v6 make_network_v6(string_view, error_code&) noexcept; // TODO
1382
1383 inline network_v6
1384 make_network_v6(string_view __str)
1385 { return make_network_v6(__str, __throw_on_error{"make_network_v6"}); }
1386
1387 // @}
1388
1389 /// ip::network_v4 I/O
1390 template<typename _CharT, typename _Traits>
1391 inline basic_ostream<_CharT, _Traits>&
1392 operator<<(basic_ostream<_CharT, _Traits>& __os, const network_v4& __net)
1393 { return __os << __net.to_string(); }
1394
1395 /// ip::network_v6 I/O
1396 template<typename _CharT, typename _Traits>
1397 inline basic_ostream<_CharT, _Traits>&
1398 operator<<(basic_ostream<_CharT, _Traits>& __os, const network_v6& __net)
1399 { return __os << __net.to_string(); }
1400
1401 /// An IP endpoint.
1402 template<typename _InternetProtocol>
1403 class basic_endpoint
1404 {
1405 public:
1406 // types:
1407 using protocol_type = _InternetProtocol;
1408
1409 // constructors:
1410
1411 constexpr
1412 basic_endpoint() noexcept : _M_data()
1413 { _M_data._M_v4.sin_family = protocol_type::v4().family(); }
1414
1415 constexpr
1416 basic_endpoint(const protocol_type& __proto,
1417 port_type __port_num) noexcept
1418 : _M_data()
1419 {
1420 __glibcxx_assert(__proto == protocol_type::v4()
1421 || __proto == protocol_type::v6());
1422
1423 _M_data._M_v4.sin_family = __proto.family();
1424 _M_data._M_v4.sin_port = address_v4::_S_hton_16(__port_num);
1425 }
1426
1427 constexpr
1428 basic_endpoint(const ip::address& __addr,
1429 port_type __port_num) noexcept
1430 : _M_data()
1431 {
1432 if (__addr.is_v4())
1433 {
1434 _M_data._M_v4.sin_family = protocol_type::v4().family();
1435 _M_data._M_v4.sin_port = address_v4::_S_hton_16(__port_num);
1436 _M_data._M_v4.sin_addr.s_addr = __addr._M_v4._M_addr;
1437 }
1438 else
1439 {
1440 _M_data._M_v6 = {};
1441 _M_data._M_v6.sin6_family = protocol_type::v6().family();
1442 _M_data._M_v6.sin6_port = address_v4::_S_hton_16(__port_num);
1443 __builtin_memcpy(_M_data._M_v6.sin6_addr.s6_addr,
1444 __addr._M_v6._M_bytes.data(), 16);
1445 _M_data._M_v6.sin6_scope_id = __addr._M_v6._M_scope_id;
1446 }
1447 }
1448
1449 // members:
1450 constexpr protocol_type protocol() const noexcept
1451 {
1452 return _M_data._M_v4.sin_family == AF_INET6
1453 ? protocol_type::v6() : protocol_type::v4();
1454 }
1455
1456 constexpr ip::address
1457 address() const noexcept
1458 {
1459 ip::address __addr;
1460 if (protocol().family() == AF_INET6)
1461 {
1462 __builtin_memcpy(&__addr._M_v6._M_bytes,
1463 _M_data._M_v6.sin6_addr.s6_addr, 16);
1464 __addr._M_is_v4 = false;
1465 }
1466 else
1467 {
1468 __builtin_memcpy(&__addr._M_v4._M_addr,
1469 &_M_data._M_v4.sin_addr.s_addr, 4);
1470 }
1471 return __addr;
1472 }
1473
1474 void
1475 address(const ip::address& __addr) noexcept
1476 {
1477 if (__addr.is_v6())
1478 {
1479 _M_data._M_v6 = {};
1480 _M_data._M_v6.sin6_family = protocol_type::v6().family();
1481 __builtin_memcpy(_M_data._M_v6.sin6_addr.s6_addr,
1482 __addr._M_v6._M_bytes.data(), 16);
1483 _M_data._M_v6.sin6_scope_id = __addr._M_v6._M_scope_id;
1484 }
1485 else
1486 {
1487 _M_data._M_v4.sin_family = protocol_type::v4().family();
1488 _M_data._M_v4.sin_addr.s_addr = __addr._M_v4._M_addr;
1489 }
1490 }
1491
1492 constexpr port_type
1493 port() const noexcept
1494 { return address_v4::_S_ntoh_16(_M_data._M_v4.sin_port); }
1495
1496 void
1497 port(port_type __port_num) noexcept
1498 { _M_data._M_v4.sin_port = address_v4::_S_hton_16(__port_num); }
1499
1500 void* data() noexcept { return &_M_data; }
1501 const void* data() const noexcept { return &_M_data; }
1502 constexpr size_t size() const noexcept
1503 {
1504 return protocol().family() == AF_INET6
1505 ? sizeof(sockaddr_in6) : sizeof(sockaddr_in);
1506 }
1507
1508 void
1509 resize(size_t __s)
1510 {
1511 if ((protocol().family() == AF_INET6 && __s != sizeof(sockaddr_in6))
1512 || (protocol().family() == AF_INET && __s != sizeof(sockaddr_in)))
1513 __throw_length_error("net::ip::basic_endpoint::resize");
1514 }
1515
1516 constexpr size_t capacity() const noexcept { return sizeof(_M_data); }
1517
1518 private:
1519 union
1520 {
1521 sockaddr_in _M_v4;
1522 sockaddr_in6 _M_v6;
1523 } _M_data;
1524 };
1525
1526 /** basic_endpoint comparisons
1527 * @{
1528 */
1529
1530 template<typename _InternetProtocol>
1531 inline bool
1532 operator==(const basic_endpoint<_InternetProtocol>& __a,
1533 const basic_endpoint<_InternetProtocol>& __b)
1534 { return __a.address() == __b.address() && __a.port() == __b.port(); }
1535
1536 template<typename _InternetProtocol>
1537 inline bool
1538 operator!=(const basic_endpoint<_InternetProtocol>& __a,
1539 const basic_endpoint<_InternetProtocol>& __b)
1540 { return !(__a == __b); }
1541
1542 template<typename _InternetProtocol>
1543 inline bool
1544 operator< (const basic_endpoint<_InternetProtocol>& __a,
1545 const basic_endpoint<_InternetProtocol>& __b)
1546 {
1547 return __a.address() < __b.address()
1548 || (!(__b.address() < __a.address()) && __a.port() < __b.port());
1549 }
1550
1551 template<typename _InternetProtocol>
1552 inline bool
1553 operator> (const basic_endpoint<_InternetProtocol>& __a,
1554 const basic_endpoint<_InternetProtocol>& __b)
1555 { return __b < __a; }
1556
1557 template<typename _InternetProtocol>
1558 inline bool
1559 operator<=(const basic_endpoint<_InternetProtocol>& __a,
1560 const basic_endpoint<_InternetProtocol>& __b)
1561 { return !(__b < __a); }
1562
1563 template<typename _InternetProtocol>
1564 inline bool
1565 operator>=(const basic_endpoint<_InternetProtocol>& __a,
1566 const basic_endpoint<_InternetProtocol>& __b)
1567 { return !(__a < __b); }
1568
1569 // @}
1570
1571 /// basic_endpoint I/O
1572 template<typename _CharT, typename _Traits, typename _InternetProtocol>
1573 inline basic_ostream<_CharT, _Traits>&
1574 operator<<(basic_ostream<_CharT, _Traits>& __os,
1575 const basic_endpoint<_InternetProtocol>& __ep)
1576 {
1577 basic_ostringstream<_CharT, _Traits> __ss;
1578 if (__ep.protocol()
1579 == basic_endpoint<_InternetProtocol>::protocol_type::v6())
1580 __ss << '[' << __ep.address() << ']';
1581 else
1582 __ss << __ep.address();
1583 __ss << ':' << __ep.port();
1584 __os << __ss.str();
1585 return __os;
1586 }
1587
1588 /** Type representing a single result of name/address resolution.
1589 * @{
1590 */
1591
1592 template<typename _InternetProtocol>
1593 class basic_resolver_entry
1594 {
1595 public:
1596 // types:
1597 using protocol_type = _InternetProtocol;
1598 using endpoint_type = typename _InternetProtocol::endpoint;
1599
1600 // constructors:
1601 basic_resolver_entry() { }
1602
1603 basic_resolver_entry(const endpoint_type& __ep,
1604 string_view __h, string_view __s)
1605 : _M_ep(__ep), _M_host(__h), _M_svc(__s) { }
1606
1607 // members:
1608 endpoint_type endpoint() const { return _M_ep; }
1609 operator endpoint_type() const { return _M_ep; }
1610
1611 template<typename _Allocator = allocator<char>>
1612 __string_with<_Allocator>
1613 host_name(const _Allocator& __a = _Allocator()) const
1614 { return { _M_host, __a }; }
1615
1616 template<typename _Allocator = allocator<char>>
1617 __string_with<_Allocator>
1618 service_name(const _Allocator& __a = _Allocator()) const
1619 { return { _M_svc, __a }; }
1620
1621 private:
1622 basic_endpoint<_InternetProtocol> _M_ep;
1623 string _M_host;
1624 string _M_svc;
1625 };
1626
1627 template<typename _InternetProtocol>
1628 inline bool
1629 operator==(const basic_resolver_entry<_InternetProtocol>& __a,
1630 const basic_resolver_entry<_InternetProtocol>& __b)
1631 {
1632 return __a.endpoint() == __b.endpoint()
1633 && __a.host_name() == __b.host_name()
1634 && __a.service_name() == __b.service_name();
1635 }
1636
1637 template<typename _InternetProtocol>
1638 inline bool
1639 operator!=(const basic_resolver_entry<_InternetProtocol>& __a,
1640 const basic_resolver_entry<_InternetProtocol>& __b)
1641 { return !(__a == __b); }
1642
1643 // @}
1644
1645 /** Base class defining flags for name/address resolution.
1646 * @{
1647 */
1648
1649 class resolver_base
1650 {
1651 public:
1652 enum flags : int
1653 {
1654 __flags_passive = AI_PASSIVE,
1655 __flags_canonical_name = AI_CANONNAME,
1656 __flags_numeric_host = AI_NUMERICHOST,
1657 #ifdef AI_NUMERICSERV
1658 __flags_numeric_service = AI_NUMERICSERV,
1659 #endif
1660 __flags_v4_mapped = AI_V4MAPPED,
1661 __flags_all_matching = AI_ALL,
1662 __flags_address_configured = AI_ADDRCONFIG
1663 };
1664 static constexpr flags passive = __flags_passive;
1665 static constexpr flags canonical_name = __flags_canonical_name;
1666 static constexpr flags numeric_host = __flags_numeric_host;
1667 #ifdef AI_NUMERICSERV
1668 static constexpr flags numeric_service = __flags_numeric_service;
1669 #endif
1670 static constexpr flags v4_mapped = __flags_v4_mapped;
1671 static constexpr flags all_matching = __flags_all_matching;
1672 static constexpr flags address_configured = __flags_address_configured;
1673
1674 protected:
1675 resolver_base() = default;
1676 ~resolver_base() = default;
1677 };
1678
1679 constexpr resolver_base::flags
1680 operator&(resolver_base::flags __f1, resolver_base::flags __f2)
1681 { return resolver_base::flags( int(__f1) & int(__f2) ); }
1682
1683 constexpr resolver_base::flags
1684 operator|(resolver_base::flags __f1, resolver_base::flags __f2)
1685 { return resolver_base::flags( int(__f1) | int(__f2) ); }
1686
1687 constexpr resolver_base::flags
1688 operator^(resolver_base::flags __f1, resolver_base::flags __f2)
1689 { return resolver_base::flags( int(__f1) ^ int(__f2) ); }
1690
1691 constexpr resolver_base::flags
1692 operator~(resolver_base::flags __f)
1693 { return resolver_base::flags( ~int(__f) ); }
1694
1695 inline resolver_base::flags&
1696 operator&=(resolver_base::flags& __f1, resolver_base::flags __f2)
1697 { return __f1 = (__f1 & __f2); }
1698
1699 inline resolver_base::flags&
1700 operator|=(resolver_base::flags& __f1, resolver_base::flags __f2)
1701 { return __f1 = (__f1 | __f2); }
1702
1703 inline resolver_base::flags&
1704 operator^=(resolver_base::flags& __f1, resolver_base::flags __f2)
1705 { return __f1 = (__f1 ^ __f2); }
1706
1707 // TODO define resolver_base::flags static constants for C++14 mode
1708
1709 // @}
1710
1711 /** Container for results of name/address resolution.
1712 * @{
1713 */
1714
1715 template<typename _InternetProtocol>
1716 class basic_resolver_results
1717 {
1718 public:
1719 // types:
1720 using protocol_type = _InternetProtocol;
1721 using endpoint_type = typename protocol_type::endpoint;
1722 using value_type = basic_resolver_entry<protocol_type>;
1723 using const_reference = const value_type&;
1724 using reference = value_type&;
1725 using const_iterator = typename forward_list<value_type>::const_iterator;
1726 using iterator = const_iterator;
1727 using difference_type = ptrdiff_t;
1728 using size_type = size_t;
1729
1730 // construct / copy / destroy:
1731
1732 basic_resolver_results() = default;
1733
1734 basic_resolver_results(const basic_resolver_results&) = default;
1735
1736 basic_resolver_results(basic_resolver_results&&) noexcept = default;
1737
1738 basic_resolver_results&
1739 operator=(const basic_resolver_results&) = default;
1740
1741 basic_resolver_results&
1742 operator=(basic_resolver_results&&) = default;
1743
1744 ~basic_resolver_results() = default;
1745
1746 // size:
1747 size_type size() const noexcept { return _M_size; }
1748 size_type max_size() const noexcept { return _M_results.max_size(); }
1749
1750 _GLIBCXX_NODISCARD bool
1751 empty() const noexcept { return _M_results.empty(); }
1752
1753 // element access:
1754 const_iterator begin() const { return _M_results.begin(); }
1755 const_iterator end() const { return _M_results.end(); }
1756 const_iterator cbegin() const { return _M_results.begin(); }
1757 const_iterator cend() const { return _M_results.end(); }
1758
1759 // swap:
1760 void
1761 swap(basic_resolver_results& __that) noexcept
1762 { _M_results.swap(__that._M_results); }
1763
1764 private:
1765 friend class basic_resolver<protocol_type>;
1766
1767 basic_resolver_results(string_view, string_view, resolver_base::flags,
1768 error_code&, protocol_type* = nullptr);
1769
1770 basic_resolver_results(const endpoint_type&, error_code&);
1771
1772 forward_list<value_type> _M_results;
1773 size_t _M_size = 0;
1774 };
1775
1776 template<typename _InternetProtocol>
1777 inline bool
1778 operator==(const basic_resolver_results<_InternetProtocol>& __a,
1779 const basic_resolver_results<_InternetProtocol>& __b)
1780 {
1781 return __a.size() == __b.size()
1782 && std::equal(__a.begin(), __a.end(), __b.begin());
1783 }
1784
1785 template<typename _InternetProtocol>
1786 inline bool
1787 operator!=(const basic_resolver_results<_InternetProtocol>& __a,
1788 const basic_resolver_results<_InternetProtocol>& __b)
1789 { return !(__a == __b); }
1790
1791 // @}
1792
1793 /// Perform name/address resolution.
1794 template<typename _InternetProtocol>
1795 class basic_resolver : public resolver_base
1796 {
1797 public:
1798 // types:
1799
1800 using executor_type = io_context::executor_type;
1801 using protocol_type = _InternetProtocol;
1802 using endpoint_type = typename _InternetProtocol::endpoint;
1803 using results_type = basic_resolver_results<_InternetProtocol>;
1804
1805 // construct / copy / destroy:
1806
1807 explicit basic_resolver(io_context& __ctx) : _M_ctx(&__ctx) { }
1808
1809 basic_resolver(const basic_resolver&) = delete;
1810
1811 basic_resolver(basic_resolver&& __rhs) noexcept
1812 : _M_ctx(__rhs._M_ctx)
1813 { } // TODO move state/tasks etc.
1814
1815 ~basic_resolver() { cancel(); }
1816
1817 basic_resolver& operator=(const basic_resolver&) = delete;
1818
1819 basic_resolver& operator=(basic_resolver&& __rhs)
1820 {
1821 cancel();
1822 _M_ctx = __rhs._M_ctx;
1823 // TODO move state/tasks etc.
1824 return *this;
1825 }
1826
1827 // basic_resolver operations:
1828
1829 executor_type get_executor() noexcept { return _M_ctx->get_executor(); }
1830
1831 void cancel() { } // TODO
1832
1833 results_type
1834 resolve(string_view __host_name, string_view __service_name)
1835 {
1836 return resolve(__host_name, __service_name, resolver_base::flags(),
1837 __throw_on_error{"basic_resolver::resolve"});
1838 }
1839
1840 results_type
1841 resolve(string_view __host_name, string_view __service_name,
1842 error_code& __ec)
1843 {
1844 return resolve(__host_name, __service_name, resolver_base::flags(),
1845 __ec);
1846 }
1847
1848 results_type
1849 resolve(string_view __host_name, string_view __service_name, flags __f)
1850 {
1851 return resolve(__host_name, __service_name, __f,
1852 __throw_on_error{"basic_resolver::resolve"});
1853 }
1854
1855 results_type
1856 resolve(string_view __host_name, string_view __service_name, flags __f,
1857 error_code& __ec)
1858 { return {__host_name, __service_name, __f, __ec}; }
1859
1860 template<typename _CompletionToken>
1861 __deduced_t<_CompletionToken, void(error_code, results_type)>
1862 async_resolve(string_view __host_name, string_view __service_name,
1863 _CompletionToken&& __token)
1864 {
1865 return async_resolve(__host_name, __service_name,
1866 resolver_base::flags(),
1867 forward<_CompletionToken>(__token));
1868 }
1869
1870 template<typename _CompletionToken>
1871 __deduced_t<_CompletionToken, void(error_code, results_type)>
1872 async_resolve(string_view __host_name, string_view __service_name,
1873 flags __f, _CompletionToken&& __token); // TODO
1874
1875 results_type
1876 resolve(const protocol_type& __protocol,
1877 string_view __host_name, string_view __service_name)
1878 {
1879 return resolve(__protocol, __host_name, __service_name,
1880 resolver_base::flags(),
1881 __throw_on_error{"basic_resolver::resolve"});
1882 }
1883
1884 results_type
1885 resolve(const protocol_type& __protocol,
1886 string_view __host_name, string_view __service_name,
1887 error_code& __ec)
1888 {
1889 return resolve(__protocol, __host_name, __service_name,
1890 resolver_base::flags(), __ec);
1891 }
1892
1893 results_type
1894 resolve(const protocol_type& __protocol,
1895 string_view __host_name, string_view __service_name, flags __f)
1896 {
1897 return resolve(__protocol, __host_name, __service_name, __f,
1898 __throw_on_error{"basic_resolver::resolve"});
1899 }
1900
1901 results_type
1902 resolve(const protocol_type& __protocol,
1903 string_view __host_name, string_view __service_name,
1904 flags __f, error_code& __ec)
1905 { return {__host_name, __service_name, __f, __ec, &__protocol}; }
1906
1907 template<typename _CompletionToken>
1908 __deduced_t<_CompletionToken, void(error_code, results_type)>
1909 async_resolve(const protocol_type& __protocol,
1910 string_view __host_name, string_view __service_name,
1911 _CompletionToken&& __token)
1912 {
1913 return async_resolve(__protocol, __host_name, __service_name,
1914 resolver_base::flags(),
1915 forward<_CompletionToken>(__token));
1916 }
1917
1918 template<typename _CompletionToken>
1919 __deduced_t<_CompletionToken, void(error_code, results_type)>
1920 async_resolve(const protocol_type& __protocol,
1921 string_view __host_name, string_view __service_name,
1922 flags __f, _CompletionToken&& __token); // TODO
1923
1924 results_type
1925 resolve(const endpoint_type& __ep)
1926 { return resolve(__ep, __throw_on_error{"basic_resolver::resolve"}); }
1927
1928 results_type
1929 resolve(const endpoint_type& __ep, error_code& __ec)
1930 { return { __ep, __ec }; }
1931
1932 template<typename _CompletionToken> // TODO
1933 __deduced_t<_CompletionToken, void(error_code, results_type)>
1934 async_resolve(const endpoint_type& __ep, _CompletionToken&& __token);
1935
1936 private:
1937 io_context* _M_ctx;
1938 };
1939
1940 /// Private constructor to synchronously resolve host and service names.
1941 template<typename _InternetProtocol>
1942 basic_resolver_results<_InternetProtocol>::
1943 basic_resolver_results(string_view __host_name, string_view __service_name,
1944 resolver_base::flags __f, error_code& __ec,
1945 protocol_type* __protocol)
1946 {
1947 #ifdef _GLIBCXX_HAVE_NETDB_H
1948 string __host;
1949 const char* __h = __host_name.data()
1950 ? (__host = __host_name.to_string()).c_str()
1951 : nullptr;
1952 string __svc;
1953 const char* __s = __service_name.data()
1954 ? (__svc = __service_name.to_string()).c_str()
1955 : nullptr;
1956
1957 ::addrinfo __hints{ };
1958 __hints.ai_flags = static_cast<int>(__f);
1959 if (__protocol)
1960 {
1961 __hints.ai_family = __protocol->family();
1962 __hints.ai_socktype = __protocol->type();
1963 __hints.ai_protocol = __protocol->protocol();
1964 }
1965 else
1966 {
1967 auto __p = endpoint_type{}.protocol();
1968 __hints.ai_family = AF_UNSPEC;
1969 __hints.ai_socktype = __p.type();
1970 __hints.ai_protocol = __p.protocol();
1971 }
1972
1973 struct __scoped_addrinfo
1974 {
1975 ~__scoped_addrinfo() { if (_M_p) ::freeaddrinfo(_M_p); }
1976 ::addrinfo* _M_p = nullptr;
1977 } __sai;
1978
1979 if (int __err = ::getaddrinfo(__h, __s, &__hints, &__sai._M_p))
1980 {
1981 __ec.assign(__err, resolver_category());
1982 return;
1983 }
1984 __ec.clear();
1985
1986 endpoint_type __ep;
1987 auto __tail = _M_results.before_begin();
1988 for (auto __ai = __sai._M_p; __ai != nullptr; __ai = __ai->ai_next)
1989 {
1990 if (__ai->ai_family == AF_INET || __ai->ai_family == AF_INET6)
1991 {
1992 if (__ai->ai_addrlen <= __ep.capacity())
1993 __builtin_memcpy(__ep.data(), __ai->ai_addr, __ai->ai_addrlen);
1994 __ep.resize(__ai->ai_addrlen);
1995 __tail = _M_results.emplace_after(__tail, __ep, __host, __svc);
1996 _M_size++;
1997 }
1998 }
1999 #else
2000 __ec = std::make_error_code(errc::operation_not_supported);
2001 #endif
2002 }
2003
2004 /// Private constructor to synchronously resolve an endpoint.
2005 template<typename _InternetProtocol>
2006 basic_resolver_results<_InternetProtocol>::
2007 basic_resolver_results(const endpoint_type& __ep, error_code& __ec)
2008 {
2009 #ifdef _GLIBCXX_HAVE_NETDB_H
2010 char __host_name[256];
2011 char __service_name[128];
2012 int __flags = 0;
2013 if (__ep.protocol().type() == SOCK_DGRAM)
2014 __flags |= NI_DGRAM;
2015 auto __sa = static_cast<const sockaddr*>(__ep.data());
2016 int __err = ::getnameinfo(__sa, __ep.size(),
2017 __host_name, sizeof(__host_name),
2018 __service_name, sizeof(__service_name),
2019 __flags);
2020 if (__err)
2021 {
2022 __flags |= NI_NUMERICSERV;
2023 __err = ::getnameinfo(__sa, __ep.size(),
2024 __host_name, sizeof(__host_name),
2025 __service_name, sizeof(__service_name),
2026 __flags);
2027 }
2028 if (__err)
2029 __ec.assign(__err, resolver_category());
2030 else
2031 {
2032 __ec.clear();
2033 _M_results.emplace_front(__ep, __host_name, __service_name);
2034 _M_size = 1;
2035 }
2036 #else
2037 __ec = std::make_error_code(errc::operation_not_supported);
2038 #endif
2039 }
2040
2041 /** The name of the local host.
2042 * @{
2043 */
2044
2045 template<typename _Allocator>
2046 __string_with<_Allocator>
2047 host_name(const _Allocator& __a, error_code& __ec)
2048 {
2049 #ifdef HOST_NAME_MAX
2050 constexpr size_t __maxlen = HOST_NAME_MAX;
2051 #else
2052 constexpr size_t __maxlen = 256;
2053 #endif
2054 char __buf[__maxlen + 1];
2055 if (::gethostname(__buf, __maxlen) == -1)
2056 __ec.assign(errno, generic_category());
2057 __buf[__maxlen] = '\0';
2058 return { __buf, __a };
2059 }
2060
2061 template<typename _Allocator>
2062 inline __string_with<_Allocator>
2063 host_name(const _Allocator& __a)
2064 { return host_name(__a, __throw_on_error{"host_name"}); }
2065
2066 inline string
2067 host_name(error_code& __ec)
2068 { return host_name(std::allocator<char>{}, __ec); }
2069
2070 inline string
2071 host_name()
2072 { return host_name(std::allocator<char>{}, __throw_on_error{"host_name"}); }
2073
2074 // @}
2075
2076 /// The TCP byte-stream protocol.
2077 class tcp
2078 {
2079 public:
2080 // types:
2081 using endpoint = basic_endpoint<tcp>; ///< A TCP endpoint.
2082 using resolver = basic_resolver<tcp>; ///< A TCP resolver.
2083 using socket = basic_stream_socket<tcp>; ///< A TCP socket.
2084 using acceptor = basic_socket_acceptor<tcp>; ///< A TCP acceptor.
2085 using iostream = basic_socket_iostream<tcp>; /// A TCP iostream.
2086
2087 #ifdef _GLIBCXX_HAVE_NETINET_TCP_H
2088 /// Disable coalescing of small segments (i.e. the Nagle algorithm).
2089 struct no_delay : __sockopt_crtp<no_delay, bool>
2090 {
2091 using __sockopt_crtp::__sockopt_crtp;
2092
2093 static const int _S_level = IPPROTO_TCP;
2094 static const int _S_name = TCP_NODELAY;
2095 };
2096 #endif
2097
2098 // static members:
2099
2100 /// A protocol object representing IPv4 TCP.
2101 static constexpr tcp v4() noexcept { return tcp(AF_INET); }
2102 /// A protocol object representing IPv6 TCP.
2103 static constexpr tcp v6() noexcept { return tcp(AF_INET6); }
2104
2105 tcp() = delete;
2106
2107 constexpr int family() const noexcept { return _M_family; }
2108 constexpr int type() const noexcept { return SOCK_STREAM; }
2109 constexpr int protocol() const noexcept { return IPPROTO_TCP; }
2110
2111 private:
2112 constexpr explicit tcp(int __family) : _M_family(__family) { }
2113
2114 int _M_family;
2115 };
2116
2117 /** tcp comparisons
2118 * @{
2119 */
2120
2121 inline bool
2122 operator==(const tcp& __a, const tcp& __b)
2123 { return __a.family() == __b.family(); }
2124
2125 inline bool
2126 operator!=(const tcp& __a, const tcp& __b)
2127 { return !(__a == __b); }
2128
2129 // @}
2130
2131 /// The UDP datagram protocol.
2132 class udp
2133 {
2134 public:
2135 // types:
2136 using endpoint = basic_endpoint<udp>;
2137 using resolver = basic_resolver<udp>;
2138 using socket = basic_datagram_socket<udp>;
2139
2140 // static members:
2141 static constexpr udp v4() noexcept { return udp(AF_INET); }
2142 static constexpr udp v6() noexcept { return udp(AF_INET6); }
2143
2144 udp() = delete;
2145
2146 constexpr int family() const noexcept { return _M_family; }
2147 constexpr int type() const noexcept { return SOCK_DGRAM; }
2148 constexpr int protocol() const noexcept { return IPPROTO_UDP; }
2149
2150 private:
2151 constexpr explicit udp(int __family) : _M_family(__family) { }
2152
2153 int _M_family;
2154 };
2155
2156 /** udp comparisons
2157 * @{
2158 */
2159
2160 bool
2161 operator==(const udp& __a, const udp& __b)
2162 { return __a.family() == __b.family(); }
2163
2164 inline bool
2165 operator!=(const udp& __a, const udp& __b)
2166 { return !(__a == __b); }
2167
2168 // @}
2169
2170 /// Restrict a socket created for an IPv6 protocol to IPv6 only.
2171 struct v6_only : __sockopt_crtp<v6_only, bool>
2172 {
2173 using __sockopt_crtp::__sockopt_crtp;
2174
2175 static const int _S_level = IPPROTO_IPV6;
2176 static const int _S_name = IPV6_V6ONLY;
2177 };
2178
2179 namespace unicast
2180 {
2181 /// Set the default number of hops (TTL) for outbound datagrams.
2182 struct hops : __sockopt_crtp<hops>
2183 {
2184 using __sockopt_crtp::__sockopt_crtp;
2185
2186 template<typename _Protocol>
2187 int
2188 level(const _Protocol& __p) const noexcept
2189 { return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; }
2190
2191 template<typename _Protocol>
2192 int
2193 name(const _Protocol& __p) const noexcept
2194 { return __p.family() == AF_INET6 ? IPV6_UNICAST_HOPS : IP_TTL; }
2195 };
2196 } // namespace unicast
2197
2198 namespace multicast
2199 {
2200 /// Request that a socket joins a multicast group.
2201 struct join_group
2202 {
2203 explicit
2204 join_group(const address&);
2205
2206 explicit
2207 join_group(const address_v4&, const address_v4& = address_v4::any());
2208
2209 explicit
2210 join_group(const address_v6&, unsigned int = 0);
2211
2212 template<typename _Protocol>
2213 int
2214 level(const _Protocol& __p) const noexcept
2215 { return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; }
2216
2217 template<typename _Protocol>
2218 int
2219 name(const _Protocol& __p) const noexcept
2220 {
2221 return __p.family() == AF_INET6
2222 ? IPV6_JOIN_GROUP : IP_ADD_MEMBERSHIP;
2223 }
2224 template<typename _Protocol>
2225 void*
2226 data(const _Protocol&) noexcept
2227 { return std::addressof(_M_value); }
2228
2229 template<typename _Protocol>
2230 const void*
2231 data(const _Protocol&) const noexcept
2232 { return std::addressof(_M_value); }
2233
2234 template<typename _Protocol>
2235 size_t
2236 size(const _Protocol& __p) const noexcept
2237 {
2238 return __p.family() == AF_INET6
2239 ? sizeof(_M_value._M_v6) : sizeof(_M_value._M_v4);
2240 }
2241
2242 template<typename _Protocol>
2243 void
2244 resize(const _Protocol& __p, size_t __s)
2245 {
2246 if (__s != size(__p))
2247 __throw_length_error("invalid value for socket option resize");
2248 }
2249
2250 protected:
2251 union
2252 {
2253 ipv6_mreq _M_v6;
2254 ip_mreq _M_v4;
2255 } _M_value;
2256 };
2257
2258 /// Request that a socket leaves a multicast group.
2259 struct leave_group
2260 {
2261 explicit
2262 leave_group(const address&);
2263
2264 explicit
2265 leave_group(const address_v4&, const address_v4& = address_v4::any());
2266
2267 explicit
2268 leave_group(const address_v6&, unsigned int = 0);
2269
2270 template<typename _Protocol>
2271 int
2272 level(const _Protocol& __p) const noexcept
2273 { return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; }
2274
2275 template<typename _Protocol>
2276 int
2277 name(const _Protocol& __p) const noexcept
2278 {
2279 return __p.family() == AF_INET6
2280 ? IPV6_LEAVE_GROUP : IP_DROP_MEMBERSHIP;
2281 }
2282 template<typename _Protocol>
2283 void*
2284 data(const _Protocol&) noexcept
2285 { return std::addressof(_M_value); }
2286
2287 template<typename _Protocol>
2288 const void*
2289 data(const _Protocol&) const noexcept
2290 { return std::addressof(_M_value); }
2291
2292 template<typename _Protocol>
2293 size_t
2294 size(const _Protocol& __p) const noexcept
2295 {
2296 return __p.family() == AF_INET6
2297 ? sizeof(_M_value._M_v6) : sizeof(_M_value._M_v4);
2298 }
2299
2300 template<typename _Protocol>
2301 void
2302 resize(const _Protocol& __p, size_t __s)
2303 {
2304 if (__s != size(__p))
2305 __throw_length_error("invalid value for socket option resize");
2306 }
2307
2308 protected:
2309 union
2310 {
2311 ipv6_mreq _M_v6;
2312 ip_mreq _M_v4;
2313 } _M_value;
2314 };
2315
2316 /// Specify the network interface for outgoing multicast datagrams.
2317 class outbound_interface
2318 {
2319 explicit
2320 outbound_interface(const address_v4&);
2321
2322 explicit
2323 outbound_interface(unsigned int);
2324
2325 template<typename _Protocol>
2326 int
2327 level(const _Protocol& __p) const noexcept
2328 { return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; }
2329
2330 template<typename _Protocol>
2331 int
2332 name(const _Protocol& __p) const noexcept
2333 {
2334 return __p.family() == AF_INET6
2335 ? IPV6_MULTICAST_IF : IP_MULTICAST_IF;
2336 }
2337
2338 template<typename _Protocol>
2339 const void*
2340 data(const _Protocol&) const noexcept
2341 { return std::addressof(_M_value); }
2342
2343 template<typename _Protocol>
2344 size_t
2345 size(const _Protocol& __p) const noexcept
2346 {
2347 return __p.family() == AF_INET6
2348 ? sizeof(_M_value._M_v6) : sizeof(_M_value._M_v4);
2349 }
2350
2351 protected:
2352 union {
2353 unsigned _M_v6;
2354 in_addr _M_v4;
2355 } _M_value;
2356 };
2357
2358 /// Set the default number of hops (TTL) for outbound datagrams.
2359 struct hops : __sockopt_crtp<hops>
2360 {
2361 using __sockopt_crtp::__sockopt_crtp;
2362
2363 template<typename _Protocol>
2364 int
2365 level(const _Protocol& __p) const noexcept
2366 { return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; }
2367
2368 template<typename _Protocol>
2369 int
2370 name(const _Protocol& __p) const noexcept
2371 {
2372 return __p.family() == AF_INET6
2373 ? IPV6_MULTICAST_HOPS : IP_MULTICAST_TTL;
2374 }
2375 };
2376
2377 /// Set whether datagrams are delivered back to the local application.
2378 struct enable_loopback : __sockopt_crtp<enable_loopback>
2379 {
2380 using __sockopt_crtp::__sockopt_crtp;
2381
2382 template<typename _Protocol>
2383 int
2384 level(const _Protocol& __p) const noexcept
2385 { return __p.family() == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP; }
2386
2387 template<typename _Protocol>
2388 int
2389 name(const _Protocol& __p) const noexcept
2390 {
2391 return __p.family() == AF_INET6
2392 ? IPV6_MULTICAST_LOOP : IP_MULTICAST_LOOP;
2393 }
2394 };
2395
2396 } // namespace multicast
2397
2398 // @}
2399
2400 } // namespace ip
2401 } // namespace v1
2402 } // namespace net
2403 } // namespace experimental
2404
2405 template<>
2406 struct is_error_condition_enum<experimental::net::v1::ip::resolver_errc>
2407 : public true_type {};
2408
2409 // hash support
2410 template<typename _Tp> struct hash;
2411 template<>
2412 struct hash<experimental::net::v1::ip::address>
2413 : __hash_base<size_t, experimental::net::v1::ip::address>
2414 {
2415 size_t
2416 operator()(const experimental::net::v1::ip::address& __a) const
2417 {
2418 if (__a.is_v4())
2419 return _Hash_impl::hash(__a.to_v4());
2420 else
2421 return _Hash_impl::hash(__a.to_v6());
2422 }
2423 };
2424
2425 template<>
2426 struct hash<experimental::net::v1::ip::address_v4>
2427 : __hash_base<size_t, experimental::net::v1::ip::address_v4>
2428 {
2429 size_t
2430 operator()(const experimental::net::v1::ip::address_v4& __a) const
2431 { return _Hash_impl::hash(__a.to_bytes()); }
2432 };
2433
2434 template<> struct hash<experimental::net::v1::ip::address_v6>
2435 : __hash_base<size_t, experimental::net::v1::ip::address_v6>
2436 {
2437 size_t
2438 operator()(const experimental::net::v1::ip::address_v6& __a) const
2439 { return _Hash_impl::hash(__a.to_bytes()); }
2440 };
2441
2442 _GLIBCXX_END_NAMESPACE_VERSION
2443 } // namespace std
2444
2445 #endif // C++14
2446
2447 #endif // _GLIBCXX_EXPERIMENTAL_INTERNET