1 // Networking implementation details -*- C++ -*-
3 // Copyright (C) 2015-2024 Free Software Foundation, Inc.
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)
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.
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.
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/>.
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}
30 #ifndef _GLIBCXX_EXPERIMENTAL_NET_H
31 #define _GLIBCXX_EXPERIMENTAL_NET_H 1
33 #pragma GCC system_header
35 #if __cplusplus >= 201402L
37 #include <type_traits>
38 #include <system_error>
39 #include <experimental/netfwd>
41 #if __cplusplus > 201703L
45 namespace std
_GLIBCXX_VISIBILITY(default)
47 _GLIBCXX_BEGIN_NAMESPACE_VERSION
48 namespace experimental
55 /** @addtogroup networking-ts
59 template<typename _CompletionToken
, typename _Signature
, typename
>
62 /// @cond undocumented
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
;
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
&&>
76 struct __throw_on_error
79 __throw_on_error(const char* __msg
) : _M_msg(__msg
) { }
81 ~__throw_on_error() noexcept(false)
84 _GLIBCXX_THROW_OR_ABORT(system_error(_M_ec
, _M_msg
));
87 __throw_on_error(const __throw_on_error
&) = delete;
88 __throw_on_error
& operator=(const __throw_on_error
&) = delete;
90 operator error_code
&() noexcept
{ return _M_ec
; }
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
106 __sockopt_base() = default;
109 __sockopt_base(_Tp __val
) noexcept(noexcept(_Tp(std::declval
<_Tp
&>())))
113 template<typename _Protocol
>
115 data(const _Protocol
&) noexcept
116 { return std::addressof(_M_value
); }
118 template<typename _Protocol
>
120 data(const _Protocol
&) const noexcept
121 { return std::addressof(_M_value
); }
123 template<typename _Protocol
>
125 size(const _Protocol
&) const noexcept
126 { return sizeof(_M_value
); }
128 template<typename _Protocol
>
130 resize(const _Protocol
&, size_t __s
)
132 if (__s
!= sizeof(_M_value
))
133 __throw_length_error("invalid value for socket option resize");
140 // Base class for types meeting BooleanSocketOption requirements.
142 struct __sockopt_base
<bool> : __sockopt_base
<int, false>
144 __sockopt_base() = default;
147 __sockopt_base(bool __val
) noexcept
148 : __sockopt_base
<int, false>(__val
)
151 bool value() const noexcept
{ return this->_M_value
; }
152 explicit operator bool() const noexcept
{ return value(); }
153 bool operator!() const noexcept
{ return !value(); }
156 // Base class for types meeting IntegerSocketOption requirements.
158 struct __sockopt_base
<int> : __sockopt_base
<int, false>
160 using __sockopt_base
<int, false>::__sockopt_base
;
162 int value() const noexcept
{ return this->_M_value
; }
165 template<typename _Derived
, typename _Tp
= int>
166 struct __sockopt_crtp
: __sockopt_base
<_Tp
>
168 using __sockopt_base
<_Tp
>::__sockopt_base
;
171 operator=(_Tp __value
) noexcept(noexcept(__value
= __value
))
173 __sockopt_base
<_Tp
>::_M_value
= __value
;
174 return static_cast<_Derived
&>(*this);
177 template<typename _Protocol
>
179 level(const _Protocol
&) const noexcept
180 { return _Derived::_S_level
; }
182 template<typename _Protocol
>
184 name(const _Protocol
&) const noexcept
185 { return _Derived::_S_name
; }
190 #if __cpp_lib_concepts
191 template<typename _Tp
>
192 concept __protocol_like
193 = copyable
<_Tp
> && requires
{ typename
_Tp::endpoint
; };
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
>;
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
)
209 { __a
.data() } -> same_as
<const void*>;
210 { __b
.data() } -> same_as
<void*>;
211 { __b
.size() } -> same_as
<size_t>;
213 { __a
.capacity() } -> same_as
<size_t>;
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
>;
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>;
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
>>;
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
;
245 && same_as
<typename
_Tp::resolver
, ip::basic_resolver
<_Tp
>>;
248 // Check Endpoint requirements for extensible implementations
249 template<typename _Tp
, typename
= void>
250 struct __is_endpoint
: false_type
253 template<typename _Tp
>
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>
264 __void_t
< typename
_Tp::protocol_type::endpoint
,
265 decltype(__b
->resize(std::declval
<size_t>())) >>;
267 template<typename _Tp
>
268 struct __is_endpoint
<_Tp
, decltype(__detail::__endpoint_reqs
<_Tp
>())>
272 // Check Protocol requirements for extensible implementations.
273 template<typename _Tp
, typename
= void>
277 template<typename _Tp
>
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>
288 template<typename _Tp
>
289 struct __is_protocol
<_Tp
, decltype(__detail::__protocol_reqs
<_Tp
>())>
293 // Check AcceptableProtocol requirements
294 template<typename _Tp
, typename
= void>
295 struct __is_acceptable_protocol
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
304 // Check InternetProtocol requirements
305 template<typename _Tp
, typename
= void>
306 struct __is_inet_protocol
309 template<typename _Tp
>
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>
321 template<typename _Tp
>
322 struct __is_inet_protocol
<_Tp
, decltype(__inet_proto_reqs
<_Tp
>())>
325 // Variable templates for requirements (with same names as concepts above).
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
;
334 } // namespace __detail
340 } // namespace experimental
341 _GLIBCXX_END_NAMESPACE_VERSION
346 #endif // _GLIBCXX_EXPERIMENTAL_NET_H