#if __cplusplus >= 201402L
#include <experimental/netfwd>
+#include <experimental/io_context>
+#include <experimental/bits/net.h>
#include <array>
#include <forward_list>
#include <sstream>
-#include <typeinfo>
-#include <cstring>
#include <cstdint>
-#include <experimental/io_context>
-#include <experimental/bits/net.h>
#include <experimental/string_view>
-#include <unistd.h>
-#include <arpa/inet.h>
-#include <netinet/tcp.h>
-#include <netdb.h>
+#ifdef _GLIBCXX_HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
+# include <sys/socket.h> // AF_INET, AF_INET6, SOCK_DGRAM, SOCK_STREAM
+#endif
+#ifdef _GLIBCXX_HAVE_ARPA_INET_H
+# include <arpa/inet.h> // inet_ntop
+#endif
+#ifdef _GLIBCXX_HAVE_NETINET_TCP_H
+# include <netinet/tcp.h> // TCP_NODELAY
+#endif
+#ifdef _GLIBCXX_HAVE_NETDB_H
+# include <netdb.h> // getaddrinfo etc.
+#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
* @{
*/
+#ifdef _GLIBCXX_HAVE_NETDB_H
/** Error codes for resolver errors.
* @{
*/
{ return error_condition(static_cast<int>(__e), resolver_category()); }
/// @}
+#endif
typedef uint_least16_t port_type; ///< Type used for port numbers.
typedef uint_least32_t scope_id_type; ///< Type used for IPv6 scope IDs.
constexpr uint_type to_uint() const noexcept { return _S_ntoh(_M_addr); }
+#ifdef _GLIBCXX_HAVE_ARPA_INET_H
template<typename _Allocator = allocator<char>>
__string_with<_Allocator>
to_string(const _Allocator& __a = _Allocator()) const
__str.resize(0);
return __str;
}
+#endif
// static members:
static constexpr address_v4 any() noexcept { return address_v4{}; }
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
__str.resize(0);
return __str;
}
+#endif
// static members:
static constexpr address_v6
any() noexcept
{
address_v6 __addr;
- std::memcpy(&__addr._M_bytes, in6addr_any.s6_addr, 16);
+ __builtin_memcpy(&__addr._M_bytes, in6addr_any.s6_addr, 16);
return __addr;
}
loopback() noexcept
{
address_v6 __addr;
- std::memcpy(&__addr._M_bytes, in6addr_loopback.s6_addr, 16);
+ __builtin_memcpy(&__addr._M_bytes, in6addr_loopback.s6_addr, 16);
return __addr;
}
inline address_v6
make_address_v6(const char* __str, error_code& __ec) noexcept
{
- auto __p = std::strchr(__str, '%');
+ auto __p = __builtin_strchr(__str, '%');
if (__p == nullptr)
return __make_address_v6(__str, nullptr, __ec);
char __buf[64];
_M_data._M_v6 = {};
_M_data._M_v6.sin6_family = protocol_type::v6().family();
_M_data._M_v6.sin6_port = address_v4::_S_hton(__port_num);
- std::memcpy(_M_data._M_v6.sin6_addr.s6_addr,
- __addr._M_v6._M_bytes.data(), 16);
+ __builtin_memcpy(_M_data._M_v6.sin6_addr.s6_addr,
+ __addr._M_v6._M_bytes.data(), 16);
_M_data._M_v6.sin6_scope_id = __addr._M_v6._M_scope_id;
}
}
ip::address __addr;
if (protocol().family() == AF_INET6)
{
- std::memcpy(&__addr._M_v6._M_bytes,
- _M_data._M_v6.sin6_addr.s6_addr, 16);
+ __builtin_memcpy(&__addr._M_v6._M_bytes,
+ _M_data._M_v6.sin6_addr.s6_addr, 16);
__addr._M_is_v4 = false;
}
else
{
- std::memcpy(&__addr._M_v4._M_addr,
- &_M_data._M_v4.sin_addr.s_addr, 4);
+ __builtin_memcpy(&__addr._M_v4._M_addr,
+ &_M_data._M_v4.sin_addr.s_addr, 4);
}
return __addr;
}
{
_M_data._M_v6 = {};
_M_data._M_v6.sin6_family = protocol_type::v6().family();
- std::memcpy(_M_data._M_v6.sin6_addr.s6_addr,
- __addr._M_v6._M_bytes.data(), 16);
+ __builtin_memcpy(_M_data._M_v6.sin6_addr.s6_addr,
+ __addr._M_v6._M_bytes.data(), 16);
_M_data._M_v6.sin6_scope_id = __addr._M_v6._M_scope_id;
}
else
operator^=(resolver_base::flags& __f1, resolver_base::flags __f2)
{ return __f1 = (__f1 ^ __f2); }
- // TODO define resolver_base::flags static constants
+ // TODO define resolver_base::flags static constants for C++14 mode
// @}
resolver_base::flags __f, error_code& __ec,
protocol_type* __protocol)
{
+#ifdef _GLIBCXX_HAVE_NETDB_H
string __host;
const char* __h = __host_name.data()
? (__host = __host_name.to_string()).c_str()
if (__ai->ai_family == AF_INET || __ai->ai_family == AF_INET6)
{
if (__ai->ai_addrlen <= __ep.capacity())
- std::memcpy(__ep.data(), __ai->ai_addr, __ai->ai_addrlen);
+ __builtin_memcpy(__ep.data(), __ai->ai_addr, __ai->ai_addrlen);
__ep.resize(__ai->ai_addrlen);
__tail = _M_results.emplace_after(__tail, __ep, __host, __svc);
_M_size++;
}
}
+#else
+ __ec = std::make_error_code(errc::operation_not_supported);
+#endif
}
/// Private constructor to synchronously resolve an endpoint.
basic_resolver_results<_InternetProtocol>::
basic_resolver_results(const endpoint_type& __ep, error_code& __ec)
{
+#ifdef _GLIBCXX_HAVE_NETDB_H
char __host_name[256];
char __service_name[128];
int __flags = 0;
_M_results.emplace_front(__ep, __host_name, __service_name);
_M_size = 1;
}
+#else
+ __ec = std::make_error_code(errc::operation_not_supported);
+#endif
}
/** The name of the local host.
typedef basic_socket_acceptor<tcp> acceptor; ///< A TCP acceptor.
typedef basic_socket_iostream<tcp> iostream; /// A TCP iostream.
+#ifdef _GLIBCXX_HAVE_NETINET_TCP_H
/// Disable coalescing of small segments (i.e. the Nagle algorithm).
struct no_delay : __sockopt_crtp<no_delay, bool>
{
static const int _S_level = IPPROTO_TCP;
static const int _S_name = TCP_NODELAY;
};
+#endif
// static members:
#include <bits/unique_ptr.h>
#if _GLIBCXX_HAVE_UNISTD_H
# include <unistd.h>
-# include <sys/socket.h>
-# include <sys/ioctl.h>
-# include <sys/fcntl.h>
-# include <sys/uio.h>
-# include <poll.h>
+# ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
+# include <sys/socket.h> // socket etc
+# endif
+# ifdef _GLIBCXX_HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h> // ioctl
+# endif
+# ifdef _GLIBCXX_HAVE_SYS_UIO_H
+# include <sys/uio.h> // iovec
+# endif
+# ifdef _GLIBCXX_HAVE_POLL_H
+# include <poll.h> // poll, pollfd, POLLIN, POLLOUT, POLLERR
+# endif
+# ifdef _GLIBCXX_HAVE_FCNTL_H
+# include <fcntl.h> // fcntl, F_GETFL, F_SETFL
+# endif
#endif
namespace std _GLIBCXX_VISIBILITY(default)
class socket_base
{
public:
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
struct broadcast : __sockopt_crtp<broadcast, bool>
{
using __sockopt_crtp::__sockopt_crtp;
static constexpr shutdown_type shutdown_send = __shutdown_send;
static constexpr shutdown_type shutdown_both = __shutdown_both;
+#ifdef _GLIBCXX_HAVE_POLL_H
enum wait_type : int
{
__wait_read = POLLIN,
static constexpr wait_type wait_read = __wait_read;
static constexpr wait_type wait_write = __wait_write;
static constexpr wait_type wait_error = __wait_error;
+#endif
enum message_flags : int
{
static constexpr message_flags message_do_not_route = __message_dontroute;
static const int max_listen_connections = SOMAXCONN;
+#endif
protected:
socket_base() = default;
~socket_base() = default;
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
struct __msg_hdr : ::msghdr
{
#ifdef IOV_MAX
this->msg_namelen = __ep.size();
}
};
+#endif
};
constexpr socket_base::message_flags
void
native_non_blocking(bool __mode, error_code& __ec)
{
+#ifdef _GLIBCXX_HAVE_FCNTL_H
int __flags = ::fcntl(_M_sockfd, F_GETFL, 0);
if (__flags >= 0)
{
__ec.clear();
_M_bits.native_non_blocking = __mode;
}
+#else
+ __ec = std::make_error_code(std::errc::not_supported);
+#endif
}
bool
native_non_blocking() const
{
+#ifdef _GLIBCXX_HAVE_FCNTL_H
if (_M_bits.native_non_blocking == -1)
{
const int __flags = ::fcntl(_M_sockfd, F_GETFL, 0);
_M_bits.native_non_blocking = __flags & O_NONBLOCK;
}
return _M_bits.native_non_blocking;
+#else
+ return false;
+#endif
}
io_context* _M_ctx;
void
open(const protocol_type& __protocol, error_code& __ec)
{
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
if (is_open())
__ec = socket_errc::already_open;
else
else
__ec.assign(errno, std::generic_category());
}
+#else
+ __ec = std::make_error_code(errc::operation_not_supported);
+#endif
}
void
void
io_control(_IoControlCommand& __command, error_code& __ec)
{
- int __result = ::ioctl(_M_sockfd, __command.name(_M_protocol),
- __command.data(_M_protocol));
+#ifdef _GLIBCXX_HAVE_SYS_IOCTL_H
+ int __result = ::ioctl(_M_sockfd, __command.name(),
+ __command.data());
if (__result == -1)
__ec.assign(errno, generic_category());
else
__ec.clear();
+#else
+ __ec = std::make_error_code(std::errc::not_supported);
+#endif
}
endpoint_type
local_endpoint(error_code& __ec) const
{
endpoint_type __endpoint;
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
socklen_t __endpoint_len = __endpoint.capacity();
if (::getsockname(_M_sockfd, (sockaddr*)__endpoint.data(),
&__endpoint_len) == -1)
}
__ec.clear();
__endpoint.resize(__endpoint_len);
+#else
+ __ec = std::make_error_code(errc::operation_not_supported);
+#endif
return __endpoint;
}
void
bind(const endpoint_type& __endpoint, error_code& __ec)
{
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
if (::bind(_M_sockfd, (sockaddr*)__endpoint.data(), __endpoint.size())
== -1)
__ec.assign(errno, generic_category());
else
__ec.clear();
+#else
+ __ec = std::make_error_code(errc::operation_not_supported);
+#endif
}
_Protocol _M_protocol{ endpoint_type{}.protocol() };
bool
at_mark(error_code& __ec) const
{
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
const int __result = ::sockatmark(native_handle());
if (__result == -1)
{
}
__ec.clear();
return (bool)__result;
+#else
+ __ec = std::make_error_code(errc::operation_not_supported);
+ return false;
+#endif
}
size_t
__ec = std::make_error_code(errc::bad_file_descriptor);
return 0;
}
-#ifdef FIONREAD
+#if defined _GLIBCXX_HAVE_SYS_IOCTL_H && defined FIONREAD
int __avail = 0;
if (::ioctl(this->_M_sockfd, FIONREAD, &__avail) == -1)
{
void
shutdown(shutdown_type __what, error_code& __ec)
{
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
if (::shutdown(native_handle(), static_cast<int>(__what)) == -1)
__ec.assign(errno, generic_category());
else
__ec.clear();
+#else
+ __ec = std::make_error_code(errc::operation_not_supported);
+#endif
}
endpoint_type
remote_endpoint(error_code& __ec) const
{
endpoint_type __endpoint;
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
socklen_t __endpoint_len = __endpoint.capacity();
if (::getpeername(this->_M_sockfd, (sockaddr*)__endpoint.data(),
&__endpoint_len)
}
__ec.clear();
__endpoint.resize(__endpoint_len);
+#else
+ __ec = std::make_error_code(errc::operation_not_supported);
+#endif
return __endpoint;
}
if (__ec)
return;
}
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
if (::connect(native_handle(), (const sockaddr*)__endpoint.data(),
__endpoint.size()) == -1)
__ec.assign(errno, generic_category());
else
__ec.clear();
+#else
+ __ec = std::make_error_code(errc::operation_not_supported);
+#endif
}
template<typename _CompletionToken>
__ep = std::move(__endpoint),
__fd = native_handle()]
(error_code __ec) mutable {
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
if (!__ec && ::connect(__fd, (const sockaddr*)__ep.data(),
__ep.size()) == -1)
__ec.assign(errno, generic_category());
+#else
+ __ec = std::make_error_code(errc::operation_not_supported);
+#endif
__h(__ec);
});
return __init.result.get();
void
wait(wait_type __w, error_code& __ec)
{
+#ifdef _GLIBCXX_HAVE_POLL_H
::pollfd __fd;
__fd.fd = native_handle();
__fd.events = static_cast<int>(__w);
__ec.assign(errno, generic_category());
else
__ec.clear();
+#else
+ __ec = std::make_error_code(errc::operation_not_supported);
+#endif
}
template<typename _CompletionToken>
receive(const _MutableBufferSequence& __buffers,
socket_base::message_flags __flags, error_code& __ec)
{
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
socket_base::__msg_hdr __msg(__buffers);
ssize_t __result = ::recvmsg(this->native_handle(), &__msg,
static_cast<int>(__flags));
}
__ec.clear();
return __result;
+#else
+ __ec = std::make_error_code(errc::operation_not_supported);
+ return 0;
+#endif
}
template<typename _MutableBufferSequence, typename _CompletionToken>
__h(__ec);
return;
}
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
socket_base::__msg_hdr __msg(__buffers);
ssize_t __result = ::recvmsg(__fd, &__msg, __flags);
if (__result == -1)
else
__ec.clear();
__h(__ec, __result);
+#else
+ __h(std::make_error_code(errc::operation_not_supported), 0);
+#endif
});
return __init.result.get();
}
socket_base::message_flags __flags,
error_code& __ec)
{
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
socket_base::__msg_hdr __msg(__buffers, __sender);
ssize_t __result = ::recvmsg(this->native_handle(), &__msg,
static_cast<int>(__flags));
__ec.clear();
__sender.resize(__msg.msg_namelen);
return __result;
+#else
+ __ec = std::make_error_code(errc::operation_not_supported);
+ return 0;
+#endif
}
template<typename _MutableBufferSequence, typename _CompletionToken>
__h(__ec);
return;
}
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
socket_base::__msg_hdr __msg(__buffers, __sender);
ssize_t __result = ::recvmsg(__fd, &__msg, __flags);
if (__result == -1)
__sender.resize(__msg.msg_namelen);
}
__h(__ec, __result);
+#else
+ __h(std::make_error_code(errc::operation_not_supported), 0);
+#endif
});
return __init.result.get();
}
send(const _ConstBufferSequence& __buffers,
socket_base::message_flags __flags, error_code& __ec)
{
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
socket_base::__msg_hdr __msg(__buffers);
ssize_t __result = ::sendmsg(this->native_handle(), &__msg,
static_cast<int>(__flags));
}
__ec.clear();
return __result;
+#else
+ __ec = std::make_error_code(errc::operation_not_supported);
+ return 0;
+#endif
}
template<typename _ConstBufferSequence, typename _CompletionToken>
__h(__ec);
return;
}
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
socket_base::__msg_hdr __msg(__buffers);
ssize_t __result = ::sendmsg(__fd, &__msg, __flags);
if (__result == -1)
else
__ec.clear();
__h(__ec, __result);
+#else
+ __h(std::make_error_code(errc::operation_not_supported), 0);
+#endif
});
return __init.result.get();
}
const endpoint_type& __recipient,
socket_base::message_flags __flags, error_code& __ec)
{
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
socket_base::__msg_hdr __msg(__buffers, __recipient);
ssize_t __result = ::sendmsg(this->native_handle(), &__msg,
static_cast<int>(__flags));
__ec.clear();
__recipient.resize(__msg.msg_namelen);
return __result;
+#else
+ __ec = std::make_error_code(errc::operation_not_supported);
+ return 0;
+#endif
}
template<typename _ConstBufferSequence, typename _CompletionToken>
__h(__ec);
return;
}
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
socket_base::__msg_hdr __msg(__buffers, __recipient);
ssize_t __result = ::sendmsg(__fd, &__msg, __flags);
if (__result == -1)
__recipient.resize(__msg.msg_namelen);
}
__h(__ec, __result);
+#else
+ __h(std::make_error_code(errc::operation_not_supported), 0);
+#endif
});
return __init.result.get();
}
__ec.clear();
return 0;
}
-
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
socket_base::__msg_hdr __msg(__buffers);
ssize_t __result = ::recvmsg(this->native_handle(), &__msg,
static_cast<int>(__flags));
return __result;
}
__ec.assign(errno, generic_category());
+#else
+ __ec = std::make_error_code(errc::operation_not_supported);
+#endif
return 0;
}
__h(__ec);
return;
}
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
socket_base::__msg_hdr __msg(__buffers);
ssize_t __result = ::recvmsg(__fd, &__msg, __flags);
if (__result == -1)
else
__ec.clear();
__h(__ec, __result);
+#else
+ __h(std::make_error_code(errc::operation_not_supported), 0);
+#endif
});
return __init.result.get();
}
__ec.clear();
return 0;
}
-
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
socket_base::__msg_hdr __msg(__buffers);
ssize_t __result = ::sendmsg(this->native_handle(), &__msg,
static_cast<int>(__flags));
return __result;
}
__ec.assign(errno, generic_category());
+#else
+ __ec = std::make_error_code(errc::operation_not_supported);
+#endif
return 0;
}
__h(__ec);
return;
}
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
socket_base::__msg_hdr __msg(__buffers);
ssize_t __result = ::sendmsg(__fd, &__msg, __flags);
if (__result == -1)
else
__ec.clear();
__h(__ec, __result);
+#else
+ __h(std::make_error_code(errc::operation_not_supported), 0);
+#endif
});
return __init.result.get();
}
__throw_on_error{"basic_socket_acceptor::listen"});
}
- void listen(int __backlog, error_code& __ec)
+ void
+ listen(int __backlog, error_code& __ec)
{
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
if (::listen(native_handle(), __backlog) == -1)
__ec.assign(errno, generic_category());
else
__ec.clear();
+#else
+ __ec = std::make_error_code(errc::operation_not_supported);
+#endif
}
endpoint_type
socket_type
accept(io_context& __ctx, error_code& __ec)
{
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
do
{
int __h = ::accept(native_handle(), nullptr, 0);
}
} while (errno == ECONNABORTED && enable_connection_aborted());
__ec.assign(errno, generic_category());
+#else
+ __ec = std::make_error_code(errc::operation_not_supported);
+#endif
return socket_type{__ctx};
}
__h(__ec, socket_type(__ctx));
return;
}
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
do
{
int __newfd = ::accept(__fd, nullptr, 0);
} while (errno == ECONNABORTED && __connabort);
__ec.assign(errno, generic_category());
__h(__ec, socket_type(__ctx));
+#else
+ __h(std::make_error_code(errc::operation_not_supported), 0);
+#endif
});
return __init.result.get();
}
socket_type
accept(io_context& __ctx, endpoint_type& __endpoint, error_code& __ec)
{
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
do
{
socklen_t __len = __endpoint.capacity();
}
} while (errno == ECONNABORTED && enable_connection_aborted());
__ec.assign(errno, generic_category());
+#else
+ __ec = std::make_error_code(errc::operation_not_supported);
+#endif
return socket_type{__ctx};
}
__h(__ec, socket_type(__ctx));
return;
}
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
do
{
socklen_t __len = __ep.capacity();
}
} while (errno == ECONNABORTED && __connabort);
__ec.assign(errno, generic_category());
+#else
+ __ec = std::make_error_code(errc::operation_not_supported);
+#endif
__h(__ec, socket_type(__ctx));
});
return __init.result.get();
void
wait(wait_type __w, error_code& __ec)
{
+#ifdef _GLIBCXX_HAVE_POLL_H
::pollfd __fds;
__fds.fd = native_handle();
__fds.events = __w; // __w | POLLIN;
__ec.assign(errno, generic_category());
else
__ec.clear();
+#else
+ __ec = std::make_error_code(errc::operation_not_supported);
+#endif
}
template<class _CompletionToken>