]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/include/experimental/bits/net.h
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / include / experimental / bits / net.h
1 // Networking implementation details -*- C++ -*-
2
3 // Copyright (C) 2015-2024 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/bits/net.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{experimental/net}
28 */
29
30 #ifndef _GLIBCXX_EXPERIMENTAL_NET_H
31 #define _GLIBCXX_EXPERIMENTAL_NET_H 1
32
33 #pragma GCC system_header
34
35 #if __cplusplus >= 201402L
36
37 #include <type_traits>
38 #include <system_error>
39 #include <experimental/netfwd>
40
41 #if __cplusplus > 201703L
42 # include <concepts>
43 #endif
44
45 namespace std _GLIBCXX_VISIBILITY(default)
46 {
47 _GLIBCXX_BEGIN_NAMESPACE_VERSION
48 namespace experimental
49 {
50 namespace net
51 {
52 inline namespace v1
53 {
54
55 /** @addtogroup networking-ts
56 * @{
57 */
58
59 template<typename _CompletionToken, typename _Signature, typename>
60 class async_result;
61
62 /// @cond undocumented
63
64 // A type denoted by DEDUCED in the TS.
65 template<typename _CompletionToken, typename _Signature>
66 using __deduced_t = typename
67 async_result<decay_t<_CompletionToken>, _Signature, void>::return_type;
68
69 // Trait to check for construction from const/non-const lvalue/rvalue.
70 template<typename _Tp>
71 using __is_value_constructible = typename __and_<
72 is_copy_constructible<_Tp>, is_move_constructible<_Tp>,
73 is_constructible<_Tp, _Tp&>, is_constructible<_Tp, const _Tp&&>
74 >::type;
75
76 struct __throw_on_error
77 {
78 explicit
79 __throw_on_error(const char* __msg) : _M_msg(__msg) { }
80
81 ~__throw_on_error() noexcept(false)
82 {
83 if (_M_ec)
84 _GLIBCXX_THROW_OR_ABORT(system_error(_M_ec, _M_msg));
85 }
86
87 __throw_on_error(const __throw_on_error&) = delete;
88 __throw_on_error& operator=(const __throw_on_error&) = delete;
89
90 operator error_code&() noexcept { return _M_ec; }
91
92 const char* _M_msg;
93 error_code _M_ec;
94 };
95
96 /// @endcond
97
98 // Base class for types meeting both GettableSocketOption and
99 // SettableSocketOption requirements.
100 // The bool parameter allows __sockopt_base<bool> to have a
101 // __sockopt_base<int, B> base class (so that its _M_value is an int)
102 // but to have that be a distinct type from __sockopt_base<int>.
103 template<typename _Tp, bool = true>
104 struct __sockopt_base
105 {
106 __sockopt_base() = default;
107
108 explicit
109 __sockopt_base(_Tp __val) noexcept(noexcept(_Tp(std::declval<_Tp&>())))
110 : _M_value(__val)
111 { }
112
113 template<typename _Protocol>
114 void*
115 data(const _Protocol&) noexcept
116 { return std::addressof(_M_value); }
117
118 template<typename _Protocol>
119 const void*
120 data(const _Protocol&) const noexcept
121 { return std::addressof(_M_value); }
122
123 template<typename _Protocol>
124 size_t
125 size(const _Protocol&) const noexcept
126 { return sizeof(_M_value); }
127
128 template<typename _Protocol>
129 void
130 resize(const _Protocol&, size_t __s)
131 {
132 if (__s != sizeof(_M_value))
133 __throw_length_error("invalid value for socket option resize");
134 }
135
136 protected:
137 _Tp _M_value { };
138 };
139
140 // Base class for types meeting BooleanSocketOption requirements.
141 template<>
142 struct __sockopt_base<bool> : __sockopt_base<int, false>
143 {
144 __sockopt_base() = default;
145
146 explicit
147 __sockopt_base(bool __val) noexcept
148 : __sockopt_base<int, false>(__val)
149 { }
150
151 bool value() const noexcept { return this->_M_value; }
152 explicit operator bool() const noexcept { return value(); }
153 bool operator!() const noexcept { return !value(); }
154 };
155
156 // Base class for types meeting IntegerSocketOption requirements.
157 template<>
158 struct __sockopt_base<int> : __sockopt_base<int, false>
159 {
160 using __sockopt_base<int, false>::__sockopt_base;
161
162 int value() const noexcept { return this->_M_value; }
163 };
164
165 template<typename _Derived, typename _Tp = int>
166 struct __sockopt_crtp : __sockopt_base<_Tp>
167 {
168 using __sockopt_base<_Tp>::__sockopt_base;
169
170 _Derived&
171 operator=(_Tp __value) noexcept(noexcept(__value = __value))
172 {
173 __sockopt_base<_Tp>::_M_value = __value;
174 return static_cast<_Derived&>(*this);
175 }
176
177 template<typename _Protocol>
178 int
179 level(const _Protocol&) const noexcept
180 { return _Derived::_S_level; }
181
182 template<typename _Protocol>
183 int
184 name(const _Protocol&) const noexcept
185 { return _Derived::_S_name; }
186 };
187
188 namespace __detail
189 {
190 #if __cpp_lib_concepts
191 template<typename _Tp>
192 concept __protocol_like
193 = copyable<_Tp> && requires { typename _Tp::endpoint; };
194
195 // Endpoint requirements for non-extensible implementations.
196 template<typename _Tp>
197 concept __endpoint_base = semiregular<_Tp>
198 && requires { typename _Tp::protocol_type; }
199 && __protocol_like<typename _Tp::protocol_type>
200 && requires(const _Tp __a) {
201 { __a.protocol() } -> same_as<typename _Tp::protocol_type>;
202 };
203
204 // Endpoint requirements for extensible implementations.
205 template<typename _Tp>
206 concept __endpoint = __endpoint_base<_Tp>
207 && requires (const _Tp& __a, _Tp& __b, size_t __s)
208 {
209 { __a.data() } -> same_as<const void*>;
210 { __b.data() } -> same_as<void*>;
211 { __b.size() } -> same_as<size_t>;
212 __b.resize(__s);
213 { __a.capacity() } -> same_as<size_t>;
214 };
215
216 // Protocol requirements for non-extensible implementations.
217 template<typename _Tp>
218 concept __protocol_base = __protocol_like<_Tp>
219 && __endpoint_base<typename _Tp::endpoint>
220 && same_as<typename _Tp::endpoint::protocol_type, _Tp>;
221
222 // Protocol requirements for extensible implementations.
223 template<typename _Tp>
224 concept __protocol = __protocol_base<_Tp>
225 && __endpoint<typename _Tp::endpoint>
226 && requires (const _Tp __a) {
227 { __a.family() } -> same_as<int>;
228 { __a.type() } -> same_as<int>;
229 { __a.protocol() } -> same_as<int>;
230 };
231
232 template<typename _Tp>
233 concept __acceptable_protocol = __protocol<_Tp>
234 && requires { typename _Tp::socket; }
235 && move_constructible<typename _Tp::socket>
236 && derived_from<typename _Tp::socket, basic_socket<_Tp>>;
237
238 template<typename _Tp>
239 concept __inet_protocol = __acceptable_protocol<_Tp>
240 && equality_comparable<_Tp> && requires {
241 { _Tp::v4() } -> same_as<_Tp>;
242 { _Tp::v6() } -> same_as<_Tp>;
243 typename _Tp::resolver;
244 }
245 && same_as<typename _Tp::resolver, ip::basic_resolver<_Tp>>;
246
247 #else
248 // Check Endpoint requirements for extensible implementations
249 template<typename _Tp, typename = void>
250 struct __is_endpoint : false_type
251 { };
252
253 template<typename _Tp>
254 auto
255 __endpoint_reqs(const _Tp* __a = nullptr, _Tp* __b = nullptr)
256 -> enable_if_t<__and_<
257 is_default_constructible<_Tp>, __is_value_constructible<_Tp>,
258 is_same<decltype(__a->protocol()), typename _Tp::protocol_type>,
259 is_same<decltype(__a->data()), const void*>,
260 is_same<decltype(__b->data()), void*>,
261 is_same<decltype(__a->size()), size_t>,
262 is_same<decltype(__a->capacity()), size_t>
263 >::value,
264 __void_t< typename _Tp::protocol_type::endpoint,
265 decltype(__b->resize(std::declval<size_t>())) >>;
266
267 template<typename _Tp>
268 struct __is_endpoint<_Tp, decltype(__detail::__endpoint_reqs<_Tp>())>
269 : true_type
270 { };
271
272 // Check Protocol requirements for extensible implementations.
273 template<typename _Tp, typename = void>
274 struct __is_protocol
275 : false_type { };
276
277 template<typename _Tp>
278 auto
279 __protocol_reqs(const _Tp* __a = nullptr)
280 -> enable_if_t<__and_<
281 is_copy_constructible<_Tp>, is_copy_assignable<_Tp>,
282 __is_endpoint<typename _Tp::endpoint>,
283 is_same<decltype(__a->family()), int>,
284 is_same<decltype(__a->type()), int>,
285 is_same<decltype(__a->protocol()), int>
286 >::value>;
287
288 template<typename _Tp>
289 struct __is_protocol<_Tp, decltype(__detail::__protocol_reqs<_Tp>())>
290 : true_type
291 { };
292
293 // Check AcceptableProtocol requirements
294 template<typename _Tp, typename = void>
295 struct __is_acceptable_protocol
296 : false_type { };
297
298 template<typename _Tp>
299 struct __is_acceptable_protocol<_Tp, __void_t<typename _Tp::socket>>
300 : __and_<__is_protocol<_Tp>, is_move_constructible<typename _Tp::socket>,
301 is_convertible<typename _Tp::socket*, basic_socket<_Tp>*>>::type
302 { };
303
304 // Check InternetProtocol requirements
305 template<typename _Tp, typename = void>
306 struct __is_inet_protocol
307 : false_type { };
308
309 template<typename _Tp>
310 auto
311 __inet_proto_reqs(const _Tp* __a = nullptr)
312 -> enable_if_t<__and_<
313 __is_acceptable_protocol<_Tp>,
314 is_same<typename _Tp::resolver, ip::basic_resolver<_Tp>>,
315 is_same<decltype(_Tp::v4()), _Tp>,
316 is_same<decltype(_Tp::v6()), _Tp>,
317 is_convertible<decltype(*__a == *__a), bool>,
318 is_convertible<decltype(*__a != *__a), bool>
319 >::value>;
320
321 template<typename _Tp>
322 struct __is_inet_protocol<_Tp, decltype(__inet_proto_reqs<_Tp>())>
323 : true_type { };
324
325 // Variable templates for requirements (with same names as concepts above).
326
327 template<typename _Tp>
328 constexpr bool __endpoint = __is_endpoint<_Tp>::value;
329 template<typename _Tp>
330 constexpr bool __protocol = __is_protocol<_Tp>::value;
331 template<typename _Tp>
332 constexpr bool __acceptable_protocol = __is_acceptable_protocol<_Tp>::value;
333 #endif
334 } // namespace __detail
335
336 /// @}
337
338 } // namespace v1
339 } // namespace net
340 } // namespace experimental
341 _GLIBCXX_END_NAMESPACE_VERSION
342 } // namespace std
343
344 #endif // C++14
345
346 #endif // _GLIBCXX_EXPERIMENTAL_NET_H