summaryrefslogtreecommitdiff
path: root/libstdc++-v3/include/experimental
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2021-04-27 13:06:43 +0100
committerJonathan Wakely <jwakely@redhat.com>2021-04-27 14:04:36 +0100
commit9ee35a8685ee174c6914059143aceb7009d3e920 (patch)
tree78d0c0a9f2212f3b9f17b8bf7d85514b7ecfd665 /libstdc++-v3/include/experimental
parent8aadb4fedb17e7a44583a7a5a4e96b1874e1ce98 (diff)
libstdc++: Better preprocessor conditions in net::ip [PR 100286]
This improves the use of preprocessor conditionas to enable/disable members of namespace net::ip according to what is supported by the target. This fixes PR 100286 by ensuring that the to_string member functions are always defined for the address_v4 and address_v6 classes. On the other hand, the IP protocol classes and internet socket option classes aren't useful at all if the corresponding constants (such as IPPROTO_TCP or IPV6_MULTICAST_HOPS) aren't define. So those types are not defined at all if they can't be used. The net/internet/socket/opt.cc test uses __has_include to check whether or not to expect the types to be available. libstdc++-v3/ChangeLog: PR libstdc++/100286 * include/experimental/internet (resolver_errc, resolver_category()) (make_error_code, make_error_condition): Define unconditionally, only make enumerators and use of gai_strerror depend on the availability of <netdb.h>. (address_v4::to_string): Use correct constant for string length. (address_v4::to_string, address_v6::to_string): Define unconditionally, throw if unsupported. (make_address_v4, make_address_v6): Define unconditionally. Return an error if unsupported. (tcp, udp, v6_only, unicast::hops, multicast::*): Define conditionally, * testsuite/experimental/net/internet/socket/opt.cc: Check for <netinet/in.h> and <netinet/tcp.h> before using types from namespace net::ip.
Diffstat (limited to 'libstdc++-v3/include/experimental')
-rw-r--r--libstdc++-v3/include/experimental/internet57
1 files changed, 46 insertions, 11 deletions
diff --git a/libstdc++-v3/include/experimental/internet b/libstdc++-v3/include/experimental/internet
index 11961762880..6c3fad6d2aa 100644
--- a/libstdc++-v3/include/experimental/internet
+++ b/libstdc++-v3/include/experimental/internet
@@ -72,20 +72,20 @@ inline namespace v1
{
namespace ip
{
-
/** @addtogroup networking-ts
* @{
*/
-#ifdef _GLIBCXX_HAVE_NETDB_H
/** Error codes for resolver errors.
* @{
*/
enum class resolver_errc : int {
+#ifdef _GLIBCXX_HAVE_NETDB_H
host_not_found = EAI_NONAME,
host_not_found_try_again = EAI_AGAIN,
service_not_found = EAI_SERVICE
+#endif
};
/// Error category for resolver errors.
@@ -94,7 +94,13 @@ namespace ip
struct __cat : error_category
{
const char* name() const noexcept { return "resolver"; }
- std::string message(int __e) const { return ::gai_strerror(__e); }
+ std::string message(int __e) const {
+#ifdef _GLIBCXX_HAVE_NETDB_H
+ return ::gai_strerror(__e);
+#else
+ return "name resolution requires <netdb.h>";
+#endif
+ }
virtual void __message(int) { } // TODO dual ABI XXX
};
static __cat __c;
@@ -108,7 +114,6 @@ namespace ip
{ return error_condition(static_cast<int>(__e), resolver_category()); }
/// @}
-#endif
using port_type = uint_least16_t; ///< Type used for port numbers.
using scope_id_type = uint_least32_t; ///< Type used for IPv6 scope IDs.
@@ -119,6 +124,16 @@ namespace ip
= enable_if_t<std::is_same<typename _Alloc::value_type, char>::value,
std::basic_string<char, std::char_traits<char>, _Alloc>>;
+ constexpr errc
+ __unsupported_err() noexcept
+ {
+#if defined EAFNOSUPPORT
+ return std::errc::address_family_not_supported;
+#else
+ return std::errc::operation_not_supported;
+#endif
+ }
+
/** Tag indicating conversion between IPv4 and IPv4-mapped IPv6 addresses.
* @{
*/
@@ -197,20 +212,22 @@ namespace ip
constexpr uint_type
to_uint() const noexcept { return _S_ntoh_32(_M_addr); }
-#ifdef _GLIBCXX_HAVE_ARPA_INET_H
template<typename _Allocator = allocator<char>>
__string_with<_Allocator>
to_string(const _Allocator& __a = _Allocator()) const
{
+#ifdef _GLIBCXX_HAVE_ARPA_INET_H
__string_with<_Allocator> __str(__a);
- __str.resize(INET6_ADDRSTRLEN);
+ __str.resize(INET_ADDRSTRLEN);
if (inet_ntop(AF_INET, &_M_addr, &__str.front(), __str.size()))
__str.erase(__str.find('\0'));
else
__str.resize(0);
return __str;
- }
+#else
+ std::__throw_system_error((int)__unsupported_err());
#endif
+ }
// static members:
static constexpr address_v4 any() noexcept { return address_v4{}; }
@@ -338,11 +355,11 @@ namespace ip
constexpr bytes_type to_bytes() const noexcept { return _M_bytes; }
-#ifdef _GLIBCXX_HAVE_ARPA_INET_H
template<typename _Allocator = allocator<char>>
__string_with<_Allocator>
to_string(const _Allocator& __a = _Allocator()) const
{
+#ifdef _GLIBCXX_HAVE_ARPA_INET_H
__string_with<_Allocator> __str(__a);
__str.resize(INET6_ADDRSTRLEN + (_M_scope_id ? 11 : 0));
char* const __p = &__str.front();
@@ -364,8 +381,10 @@ namespace ip
else
__str.resize(0);
return __str;
- }
+#else
+ std::__throw_system_error((int)__unsupported_err());
#endif
+ }
// static members:
@@ -650,6 +669,7 @@ namespace ip
inline address_v4
make_address_v4(const char* __str, error_code& __ec) noexcept
{
+#ifdef _GLIBCXX_HAVE_ARPA_INET_H
address_v4 __a;
const int __res = ::inet_pton(AF_INET, __str, &__a._M_addr);
if (__res == 1)
@@ -661,6 +681,9 @@ namespace ip
__ec = std::make_error_code(std::errc::invalid_argument);
else
__ec.assign(errno, generic_category());
+#else
+ __ec = std::make_error_code(__unsupported_err());
+#endif
return {};
}
@@ -718,8 +741,9 @@ namespace ip
inline address_v6
__make_address_v6(const char* __addr, const char* __scope, error_code& __ec)
{
+#ifdef _GLIBCXX_HAVE_ARPA_INET_H
address_v6::bytes_type __b;
- int __res = ::inet_pton(AF_INET6, __addr, __b.data());
+ const int __res = ::inet_pton(AF_INET6, __addr, __b.data());
if (__res == 1)
{
__ec.clear();
@@ -741,6 +765,9 @@ namespace ip
__ec = std::make_error_code(std::errc::invalid_argument);
else
__ec.assign(errno, generic_category());
+#else
+ __ec = std::make_error_code(__unsupported_err());
+#endif
return {};
}
@@ -2062,6 +2089,7 @@ namespace ip
/// @}
+#ifdef IPPROTO_TCP
/// The TCP byte-stream protocol.
class tcp
{
@@ -2073,7 +2101,7 @@ namespace ip
using acceptor = basic_socket_acceptor<tcp>; ///< A TCP acceptor.
using iostream = basic_socket_iostream<tcp>; /// A TCP iostream.
-#ifdef _GLIBCXX_HAVE_NETINET_TCP_H
+#ifdef TCP_NODELAY
/// Disable coalescing of small segments (i.e. the Nagle algorithm).
struct no_delay : __sockopt_crtp<no_delay, bool>
{
@@ -2117,7 +2145,9 @@ namespace ip
{ return !(__a == __b); }
/// @}
+#endif // IPPROTO_TCP
+#ifdef IPPROTO_UDP
/// The UDP datagram protocol.
class udp
{
@@ -2156,6 +2186,9 @@ namespace ip
{ return !(__a == __b); }
/// @}
+#endif // IPPROTO_UDP
+
+#if defined IPPROTO_IP && defined IPPROTO_IPV6
/// Restrict a socket created for an IPv6 protocol to IPv6 only.
class v6_only : public __sockopt_crtp<v6_only, bool>
@@ -2371,6 +2404,8 @@ namespace ip
} // namespace multicast
+#endif // IPPROTO_IP && IPPROTO_IPV6
+
/// @}
} // namespace ip