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