]>
Commit | Line | Data |
---|---|---|
e5989e71 JW |
1 | // Networking implementation details -*- C++ -*- |
2 | ||
99dee823 | 3 | // Copyright (C) 2015-2021 Free Software Foundation, Inc. |
e5989e71 JW |
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. | |
041aa6ab | 27 | * Do not attempt to use it directly. @headername{experimental/net} |
e5989e71 JW |
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 | ||
b780db2e JW |
41 | #if __cplusplus > 201703L |
42 | # include <concepts> | |
43 | #endif | |
44 | ||
e5989e71 JW |
45 | namespace std _GLIBCXX_VISIBILITY(default) |
46 | { | |
a70a4be9 | 47 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
e5989e71 JW |
48 | namespace experimental |
49 | { | |
50 | namespace net | |
51 | { | |
52 | inline namespace v1 | |
53 | { | |
e5989e71 | 54 | |
3084625d JW |
55 | /** @addtogroup networking-ts |
56 | * @{ | |
e5989e71 JW |
57 | */ |
58 | ||
59 | template<typename _CompletionToken, typename _Signature, typename> | |
60 | class async_result; | |
61 | ||
041aa6ab JW |
62 | /// @cond undocumented |
63 | ||
e5989e71 JW |
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 | ||
041aa6ab JW |
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) | |
e5989e71 | 82 | { |
041aa6ab JW |
83 | if (_M_ec) |
84 | _GLIBCXX_THROW_OR_ABORT(system_error(_M_ec, _M_msg)); | |
85 | } | |
e5989e71 | 86 | |
041aa6ab JW |
87 | __throw_on_error(const __throw_on_error&) = delete; |
88 | __throw_on_error& operator=(const __throw_on_error&) = delete; | |
e5989e71 | 89 | |
041aa6ab | 90 | operator error_code&() noexcept { return _M_ec; } |
e5989e71 | 91 | |
041aa6ab JW |
92 | const char* _M_msg; |
93 | error_code _M_ec; | |
94 | }; | |
e5989e71 | 95 | |
041aa6ab | 96 | /// @endcond |
e5989e71 JW |
97 | |
98 | // Base class for types meeting IntegerSocketOption requirements. | |
99 | template<typename _Tp> | |
100 | struct __sockopt_base | |
101 | { | |
102 | __sockopt_base() = default; | |
103 | ||
104 | explicit __sockopt_base(int __val) : _M_value(__val) { } | |
105 | ||
106 | int value() const noexcept { return _M_value; } | |
107 | ||
108 | template<typename _Protocol> | |
109 | void* | |
110 | data(const _Protocol&) noexcept | |
111 | { return std::addressof(_M_value); } | |
112 | ||
113 | template<typename _Protocol> | |
114 | const void* | |
115 | data(const _Protocol&) const noexcept | |
116 | { return std::addressof(_M_value); } | |
117 | ||
118 | template<typename _Protocol> | |
119 | size_t | |
120 | size(const _Protocol&) const noexcept | |
121 | { return sizeof(_M_value); } | |
122 | ||
123 | template<typename _Protocol> | |
124 | void | |
125 | resize(const _Protocol&, size_t __s) | |
126 | { | |
127 | if (__s != sizeof(_M_value)) | |
128 | __throw_length_error("invalid value for socket option resize"); | |
129 | } | |
130 | ||
131 | protected: | |
132 | _Tp _M_value { }; | |
133 | }; | |
134 | ||
135 | // Base class for types meeting BooleanSocketOption requirements. | |
136 | template<> | |
137 | struct __sockopt_base<bool> : __sockopt_base<int> | |
138 | { | |
139 | __sockopt_base() = default; | |
140 | ||
141 | explicit __sockopt_base(bool __val) : __sockopt_base<int>(__val) { } | |
142 | ||
143 | bool value() const noexcept { return __sockopt_base<int>::_M_value; } | |
144 | explicit operator bool() const noexcept { return value(); } | |
145 | bool operator!() const noexcept { return !value(); } | |
146 | }; | |
147 | ||
148 | template<typename _Derived, typename _Tp = int> | |
149 | struct __sockopt_crtp : __sockopt_base<_Tp> | |
150 | { | |
151 | using __sockopt_base<_Tp>::__sockopt_base; | |
152 | ||
153 | _Derived& | |
154 | operator=(_Tp __value) | |
155 | { | |
156 | __sockopt_base<_Tp>::_M_value = __value; | |
157 | return static_cast<_Derived&>(*this); | |
158 | } | |
159 | ||
160 | template<typename _Protocol> | |
161 | int | |
162 | level(const _Protocol&) const noexcept | |
163 | { return _Derived::_S_level; } | |
164 | ||
165 | template<typename _Protocol> | |
166 | int | |
167 | name(const _Protocol&) const noexcept | |
168 | { return _Derived::_S_name; } | |
169 | }; | |
170 | ||
b780db2e JW |
171 | namespace __detail |
172 | { | |
173 | #if __cpp_lib_concepts | |
174 | template<typename _Tp> | |
175 | concept __protocol_like | |
176 | = copyable<_Tp> && requires { typename _Tp::endpoint; }; | |
177 | ||
178 | // Endpoint requirements for non-extensible implementations. | |
179 | template<typename _Tp> | |
180 | concept __endpoint_base = semiregular<_Tp> | |
181 | && requires { typename _Tp::protocol_type; } | |
182 | && __protocol_like<typename _Tp::protocol_type> | |
183 | && requires(const _Tp __a) { | |
184 | { __a.protocol() } -> same_as<typename _Tp::protocol_type>; | |
185 | }; | |
186 | ||
187 | // Endpoint requirements for extensible implementations. | |
188 | template<typename _Tp> | |
189 | concept __endpoint = __endpoint_base<_Tp> | |
190 | && requires (const _Tp& __a, _Tp& __b, size_t __s) | |
191 | { | |
192 | { __a.data() } -> same_as<const void*>; | |
193 | { __b.data() } -> same_as<void*>; | |
194 | { __b.size() } -> same_as<size_t>; | |
195 | __b.resize(__s); | |
196 | { __a.capacity() } -> same_as<size_t>; | |
197 | }; | |
198 | ||
199 | // Protocol requirements for non-extensible implementations. | |
200 | template<typename _Tp> | |
201 | concept __protocol_base = __protocol_like<_Tp> | |
202 | && __endpoint_base<typename _Tp::endpoint> | |
203 | && same_as<typename _Tp::endpoint::protocol_type, _Tp>; | |
204 | ||
205 | // Protocol requirements for extensible implementations. | |
206 | template<typename _Tp> | |
207 | concept __protocol = __protocol_base<_Tp> | |
208 | && __endpoint<typename _Tp::endpoint> | |
209 | && requires (const _Tp __a) { | |
210 | { __a.family() } -> same_as<int>; | |
211 | { __a.type() } -> same_as<int>; | |
212 | { __a.protocol() } -> same_as<int>; | |
213 | }; | |
214 | ||
215 | template<typename _Tp> | |
216 | concept __acceptable_protocol = __protocol<_Tp> | |
217 | && requires { typename _Tp::socket; } | |
218 | && move_constructible<typename _Tp::socket> | |
219 | && derived_from<typename _Tp::socket, basic_socket<_Tp>>; | |
220 | ||
221 | template<typename _Tp> | |
222 | concept __inet_protocol = __acceptable_protocol<_Tp> | |
223 | && equality_comparable<_Tp> && requires { | |
224 | { _Tp::v4() } -> same_as<_Tp>; | |
225 | { _Tp::v6() } -> same_as<_Tp>; | |
226 | typename _Tp::resolver; | |
227 | } | |
228 | && same_as<typename _Tp::resolver, ip::basic_resolver<_Tp>>; | |
229 | ||
230 | #else | |
231 | // Check Endpoint requirements for extensible implementations | |
232 | template<typename _Tp, typename = void> | |
233 | struct __is_endpoint : false_type | |
234 | { }; | |
235 | ||
236 | template<typename _Tp> | |
237 | auto | |
238 | __endpoint_reqs(const _Tp* __a = nullptr, _Tp* __b = nullptr) | |
239 | -> enable_if_t<__and_< | |
240 | is_default_constructible<_Tp>, __is_value_constructible<_Tp>, | |
241 | is_same<decltype(__a->protocol()), typename _Tp::protocol_type>, | |
242 | is_same<decltype(__a->data()), const void*>, | |
243 | is_same<decltype(__b->data()), void*>, | |
244 | is_same<decltype(__a->size()), size_t>, | |
245 | is_same<decltype(__a->capacity()), size_t> | |
246 | >::value, | |
247 | __void_t< typename _Tp::protocol_type::endpoint, | |
248 | decltype(__b->resize(std::declval<size_t>())) >>; | |
249 | ||
250 | template<typename _Tp> | |
251 | struct __is_endpoint<_Tp, decltype(__detail::__endpoint_reqs<_Tp>())> | |
252 | : true_type | |
253 | { }; | |
254 | ||
255 | // Check Protocol requirements for extensible implementations. | |
256 | template<typename _Tp, typename = void> | |
257 | struct __is_protocol | |
258 | : false_type { }; | |
259 | ||
260 | template<typename _Tp> | |
261 | auto | |
262 | __protocol_reqs(const _Tp* __a = nullptr) | |
263 | -> enable_if_t<__and_< | |
264 | is_copy_constructible<_Tp>, is_copy_assignable<_Tp>, | |
265 | __is_endpoint<typename _Tp::endpoint>, | |
266 | is_same<decltype(__a->family()), int>, | |
267 | is_same<decltype(__a->type()), int>, | |
268 | is_same<decltype(__a->protocol()), int> | |
269 | >::value>; | |
270 | ||
271 | template<typename _Tp> | |
272 | struct __is_protocol<_Tp, decltype(__detail::__protocol_reqs<_Tp>())> | |
273 | : true_type | |
274 | { }; | |
275 | ||
276 | // Check AcceptableProtocol requirements | |
277 | template<typename _Tp, typename = void> | |
278 | struct __is_acceptable_protocol | |
279 | : false_type { }; | |
280 | ||
281 | template<typename _Tp> | |
282 | struct __is_acceptable_protocol<_Tp, __void_t<typename _Tp::socket>> | |
283 | : __and_<__is_protocol<_Tp>, is_move_constructible<typename _Tp::socket>, | |
284 | is_convertible<typename _Tp::socket*, basic_socket<_Tp>*>>::type | |
285 | { }; | |
286 | ||
287 | // Check InternetProtocol requirements | |
288 | template<typename _Tp, typename = void> | |
289 | struct __is_inet_protocol | |
290 | : false_type { }; | |
291 | ||
292 | template<typename _Tp> | |
293 | auto | |
294 | __inet_proto_reqs(const _Tp* __a = nullptr) | |
295 | -> enable_if_t<__and_< | |
296 | __is_acceptable_protocol<_Tp>, | |
297 | is_same<typename _Tp::resolver, ip::basic_resolver<_Tp>>, | |
298 | is_same<decltype(_Tp::v4()), _Tp>, | |
299 | is_same<decltype(_Tp::v6()), _Tp>, | |
300 | is_convertible<decltype(*__a == *__a), bool>, | |
301 | is_convertible<decltype(*__a != *__a), bool> | |
302 | >::value>; | |
303 | ||
304 | template<typename _Tp> | |
305 | struct __is_inet_protocol<_Tp, decltype(__inet_proto_reqs<_Tp>())> | |
306 | : true_type { }; | |
307 | ||
308 | // Variable templates for requirements (with same names as concepts above). | |
309 | ||
310 | template<typename _Tp> | |
311 | constexpr bool __endpoint = __is_endpoint<_Tp>::value; | |
312 | template<typename _Tp> | |
313 | constexpr bool __protocol = __is_protocol<_Tp>::value; | |
314 | template<typename _Tp> | |
315 | constexpr bool __acceptable_protocol = __is_acceptable_protocol<_Tp>::value; | |
316 | #endif | |
317 | } // namespace __detail | |
318 | ||
e5989e71 JW |
319 | /// @} |
320 | ||
e5989e71 JW |
321 | } // namespace v1 |
322 | } // namespace net | |
323 | } // namespace experimental | |
a70a4be9 | 324 | _GLIBCXX_END_NAMESPACE_VERSION |
e5989e71 JW |
325 | } // namespace std |
326 | ||
327 | #endif // C++14 | |
328 | ||
329 | #endif // _GLIBCXX_EXPERIMENTAL_NET_H |