net.h 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. // Networking implementation details -*- C++ -*-
  2. // Copyright (C) 2015-2021 Free Software Foundation, Inc.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the
  6. // terms of the GNU General Public License as published by the
  7. // Free Software Foundation; either version 3, or (at your option)
  8. // any later version.
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // Under Section 7 of GPL version 3, you are granted additional
  14. // permissions described in the GCC Runtime Library Exception, version
  15. // 3.1, as published by the Free Software Foundation.
  16. // You should have received a copy of the GNU General Public License and
  17. // a copy of the GCC Runtime Library Exception along with this program;
  18. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. // <http://www.gnu.org/licenses/>.
  20. /** @file experimental/bits/net.h
  21. * This is an internal header file, included by other library headers.
  22. * Do not attempt to use it directly. @headername{experimental/net}
  23. */
  24. #ifndef _GLIBCXX_EXPERIMENTAL_NET_H
  25. #define _GLIBCXX_EXPERIMENTAL_NET_H 1
  26. #pragma GCC system_header
  27. #if __cplusplus >= 201402L
  28. #include <type_traits>
  29. #include <system_error>
  30. #include <experimental/netfwd>
  31. #if __cplusplus > 201703L
  32. # include <concepts>
  33. #endif
  34. namespace std _GLIBCXX_VISIBILITY(default)
  35. {
  36. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  37. namespace experimental
  38. {
  39. namespace net
  40. {
  41. inline namespace v1
  42. {
  43. /** @addtogroup networking-ts
  44. * @{
  45. */
  46. template<typename _CompletionToken, typename _Signature, typename>
  47. class async_result;
  48. /// @cond undocumented
  49. // A type denoted by DEDUCED in the TS.
  50. template<typename _CompletionToken, typename _Signature>
  51. using __deduced_t = typename
  52. async_result<decay_t<_CompletionToken>, _Signature, void>::return_type;
  53. // Trait to check for construction from const/non-const lvalue/rvalue.
  54. template<typename _Tp>
  55. using __is_value_constructible = typename __and_<
  56. is_copy_constructible<_Tp>, is_move_constructible<_Tp>,
  57. is_constructible<_Tp, _Tp&>, is_constructible<_Tp, const _Tp&&>
  58. >::type;
  59. struct __throw_on_error
  60. {
  61. explicit
  62. __throw_on_error(const char* __msg) : _M_msg(__msg) { }
  63. ~__throw_on_error() noexcept(false)
  64. {
  65. if (_M_ec)
  66. _GLIBCXX_THROW_OR_ABORT(system_error(_M_ec, _M_msg));
  67. }
  68. __throw_on_error(const __throw_on_error&) = delete;
  69. __throw_on_error& operator=(const __throw_on_error&) = delete;
  70. operator error_code&() noexcept { return _M_ec; }
  71. const char* _M_msg;
  72. error_code _M_ec;
  73. };
  74. /// @endcond
  75. // Base class for types meeting IntegerSocketOption requirements.
  76. template<typename _Tp>
  77. struct __sockopt_base
  78. {
  79. __sockopt_base() = default;
  80. explicit __sockopt_base(int __val) : _M_value(__val) { }
  81. int value() const noexcept { return _M_value; }
  82. template<typename _Protocol>
  83. void*
  84. data(const _Protocol&) noexcept
  85. { return std::addressof(_M_value); }
  86. template<typename _Protocol>
  87. const void*
  88. data(const _Protocol&) const noexcept
  89. { return std::addressof(_M_value); }
  90. template<typename _Protocol>
  91. size_t
  92. size(const _Protocol&) const noexcept
  93. { return sizeof(_M_value); }
  94. template<typename _Protocol>
  95. void
  96. resize(const _Protocol&, size_t __s)
  97. {
  98. if (__s != sizeof(_M_value))
  99. __throw_length_error("invalid value for socket option resize");
  100. }
  101. protected:
  102. _Tp _M_value { };
  103. };
  104. // Base class for types meeting BooleanSocketOption requirements.
  105. template<>
  106. struct __sockopt_base<bool> : __sockopt_base<int>
  107. {
  108. __sockopt_base() = default;
  109. explicit __sockopt_base(bool __val) : __sockopt_base<int>(__val) { }
  110. bool value() const noexcept { return __sockopt_base<int>::_M_value; }
  111. explicit operator bool() const noexcept { return value(); }
  112. bool operator!() const noexcept { return !value(); }
  113. };
  114. template<typename _Derived, typename _Tp = int>
  115. struct __sockopt_crtp : __sockopt_base<_Tp>
  116. {
  117. using __sockopt_base<_Tp>::__sockopt_base;
  118. _Derived&
  119. operator=(_Tp __value)
  120. {
  121. __sockopt_base<_Tp>::_M_value = __value;
  122. return static_cast<_Derived&>(*this);
  123. }
  124. template<typename _Protocol>
  125. int
  126. level(const _Protocol&) const noexcept
  127. { return _Derived::_S_level; }
  128. template<typename _Protocol>
  129. int
  130. name(const _Protocol&) const noexcept
  131. { return _Derived::_S_name; }
  132. };
  133. namespace __detail
  134. {
  135. #if __cpp_lib_concepts
  136. template<typename _Tp>
  137. concept __protocol_like
  138. = copyable<_Tp> && requires { typename _Tp::endpoint; };
  139. // Endpoint requirements for non-extensible implementations.
  140. template<typename _Tp>
  141. concept __endpoint_base = semiregular<_Tp>
  142. && requires { typename _Tp::protocol_type; }
  143. && __protocol_like<typename _Tp::protocol_type>
  144. && requires(const _Tp __a) {
  145. { __a.protocol() } -> same_as<typename _Tp::protocol_type>;
  146. };
  147. // Endpoint requirements for extensible implementations.
  148. template<typename _Tp>
  149. concept __endpoint = __endpoint_base<_Tp>
  150. && requires (const _Tp& __a, _Tp& __b, size_t __s)
  151. {
  152. { __a.data() } -> same_as<const void*>;
  153. { __b.data() } -> same_as<void*>;
  154. { __b.size() } -> same_as<size_t>;
  155. __b.resize(__s);
  156. { __a.capacity() } -> same_as<size_t>;
  157. };
  158. // Protocol requirements for non-extensible implementations.
  159. template<typename _Tp>
  160. concept __protocol_base = __protocol_like<_Tp>
  161. && __endpoint_base<typename _Tp::endpoint>
  162. && same_as<typename _Tp::endpoint::protocol_type, _Tp>;
  163. // Protocol requirements for extensible implementations.
  164. template<typename _Tp>
  165. concept __protocol = __protocol_base<_Tp>
  166. && __endpoint<typename _Tp::endpoint>
  167. && requires (const _Tp __a) {
  168. { __a.family() } -> same_as<int>;
  169. { __a.type() } -> same_as<int>;
  170. { __a.protocol() } -> same_as<int>;
  171. };
  172. template<typename _Tp>
  173. concept __acceptable_protocol = __protocol<_Tp>
  174. && requires { typename _Tp::socket; }
  175. && move_constructible<typename _Tp::socket>
  176. && derived_from<typename _Tp::socket, basic_socket<_Tp>>;
  177. template<typename _Tp>
  178. concept __inet_protocol = __acceptable_protocol<_Tp>
  179. && equality_comparable<_Tp> && requires {
  180. { _Tp::v4() } -> same_as<_Tp>;
  181. { _Tp::v6() } -> same_as<_Tp>;
  182. typename _Tp::resolver;
  183. }
  184. && same_as<typename _Tp::resolver, ip::basic_resolver<_Tp>>;
  185. #else
  186. // Check Endpoint requirements for extensible implementations
  187. template<typename _Tp, typename = void>
  188. struct __is_endpoint : false_type
  189. { };
  190. template<typename _Tp>
  191. auto
  192. __endpoint_reqs(const _Tp* __a = nullptr, _Tp* __b = nullptr)
  193. -> enable_if_t<__and_<
  194. is_default_constructible<_Tp>, __is_value_constructible<_Tp>,
  195. is_same<decltype(__a->protocol()), typename _Tp::protocol_type>,
  196. is_same<decltype(__a->data()), const void*>,
  197. is_same<decltype(__b->data()), void*>,
  198. is_same<decltype(__a->size()), size_t>,
  199. is_same<decltype(__a->capacity()), size_t>
  200. >::value,
  201. __void_t< typename _Tp::protocol_type::endpoint,
  202. decltype(__b->resize(std::declval<size_t>())) >>;
  203. template<typename _Tp>
  204. struct __is_endpoint<_Tp, decltype(__detail::__endpoint_reqs<_Tp>())>
  205. : true_type
  206. { };
  207. // Check Protocol requirements for extensible implementations.
  208. template<typename _Tp, typename = void>
  209. struct __is_protocol
  210. : false_type { };
  211. template<typename _Tp>
  212. auto
  213. __protocol_reqs(const _Tp* __a = nullptr)
  214. -> enable_if_t<__and_<
  215. is_copy_constructible<_Tp>, is_copy_assignable<_Tp>,
  216. __is_endpoint<typename _Tp::endpoint>,
  217. is_same<decltype(__a->family()), int>,
  218. is_same<decltype(__a->type()), int>,
  219. is_same<decltype(__a->protocol()), int>
  220. >::value>;
  221. template<typename _Tp>
  222. struct __is_protocol<_Tp, decltype(__detail::__protocol_reqs<_Tp>())>
  223. : true_type
  224. { };
  225. // Check AcceptableProtocol requirements
  226. template<typename _Tp, typename = void>
  227. struct __is_acceptable_protocol
  228. : false_type { };
  229. template<typename _Tp>
  230. struct __is_acceptable_protocol<_Tp, __void_t<typename _Tp::socket>>
  231. : __and_<__is_protocol<_Tp>, is_move_constructible<typename _Tp::socket>,
  232. is_convertible<typename _Tp::socket*, basic_socket<_Tp>*>>::type
  233. { };
  234. // Check InternetProtocol requirements
  235. template<typename _Tp, typename = void>
  236. struct __is_inet_protocol
  237. : false_type { };
  238. template<typename _Tp>
  239. auto
  240. __inet_proto_reqs(const _Tp* __a = nullptr)
  241. -> enable_if_t<__and_<
  242. __is_acceptable_protocol<_Tp>,
  243. is_same<typename _Tp::resolver, ip::basic_resolver<_Tp>>,
  244. is_same<decltype(_Tp::v4()), _Tp>,
  245. is_same<decltype(_Tp::v6()), _Tp>,
  246. is_convertible<decltype(*__a == *__a), bool>,
  247. is_convertible<decltype(*__a != *__a), bool>
  248. >::value>;
  249. template<typename _Tp>
  250. struct __is_inet_protocol<_Tp, decltype(__inet_proto_reqs<_Tp>())>
  251. : true_type { };
  252. // Variable templates for requirements (with same names as concepts above).
  253. template<typename _Tp>
  254. constexpr bool __endpoint = __is_endpoint<_Tp>::value;
  255. template<typename _Tp>
  256. constexpr bool __protocol = __is_protocol<_Tp>::value;
  257. template<typename _Tp>
  258. constexpr bool __acceptable_protocol = __is_acceptable_protocol<_Tp>::value;
  259. #endif
  260. } // namespace __detail
  261. /// @}
  262. } // namespace v1
  263. } // namespace net
  264. } // namespace experimental
  265. _GLIBCXX_END_NAMESPACE_VERSION
  266. } // namespace std
  267. #endif // C++14
  268. #endif // _GLIBCXX_EXPERIMENTAL_NET_H