include/boost/corosio/native/native_resolver.hpp

95.5% Lines (21/22) 100.0% List of functions (12/12)
native_resolver.hpp
f(x) Functions (12)
Function Calls Lines Blocks
boost::corosio::native_resolver<boost::corosio::epoll_t{}>::get_impl() :56 1x 100.0% 100.0% boost::corosio::native_resolver<boost::corosio::select_t{}>::get_impl() :56 1x 100.0% 100.0% boost::corosio::native_resolver<boost::corosio::epoll_t{}>::native_resolve_awaitable::native_resolve_awaitable(boost::corosio::native_resolver<boost::corosio::epoll_t{}>&, std::basic_string_view<char, std::char_traits<char> >, std::basic_string_view<char, std::char_traits<char> >, boost::corosio::resolve_flags) :71 1x 100.0% 100.0% boost::corosio::native_resolver<boost::corosio::select_t{}>::native_resolve_awaitable::native_resolve_awaitable(boost::corosio::native_resolver<boost::corosio::select_t{}>&, std::basic_string_view<char, std::char_traits<char> >, std::basic_string_view<char, std::char_traits<char> >, boost::corosio::resolve_flags) :71 1x 100.0% 100.0% boost::corosio::native_resolver<boost::corosio::epoll_t{}>::native_resolve_awaitable::await_ready() const :83 1x 100.0% 100.0% boost::corosio::native_resolver<boost::corosio::select_t{}>::native_resolve_awaitable::await_ready() const :83 1x 100.0% 100.0% boost::corosio::native_resolver<boost::corosio::epoll_t{}>::native_resolve_awaitable::await_resume() const :88 1x 75.0% 62.0% boost::corosio::native_resolver<boost::corosio::select_t{}>::native_resolve_awaitable::await_resume() const :88 1x 75.0% 62.0% boost::corosio::native_resolver<boost::corosio::epoll_t{}>::native_resolve_awaitable::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :95 1x 100.0% 85.0% boost::corosio::native_resolver<boost::corosio::select_t{}>::native_resolve_awaitable::await_suspend(std::__n4861::coroutine_handle<void>, boost::capy::io_env const*) :95 1x 100.0% 85.0% boost::corosio::native_resolver<boost::corosio::epoll_t{}>::native_resolver(boost::capy::execution_context&) :150 3x 100.0% 100.0% boost::corosio::native_resolver<boost::corosio::select_t{}>::native_resolver(boost::capy::execution_context&) :150 3x 100.0% 100.0%
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Steve Gerbino
3 // Copyright (c) 2026 Michael Vandeberg
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // Official repository: https://github.com/cppalliance/corosio
9 //
10
11 #ifndef BOOST_COROSIO_NATIVE_NATIVE_RESOLVER_HPP
12 #define BOOST_COROSIO_NATIVE_NATIVE_RESOLVER_HPP
13
14 #include <boost/corosio/resolver.hpp>
15 #include <boost/corosio/backend.hpp>
16
17 #ifndef BOOST_COROSIO_MRDOCS
18 #if BOOST_COROSIO_HAS_EPOLL || BOOST_COROSIO_HAS_SELECT || \
19 BOOST_COROSIO_HAS_KQUEUE
20 #include <boost/corosio/native/detail/posix/posix_resolver_service.hpp>
21 #endif
22
23 #if BOOST_COROSIO_HAS_IOCP
24 #include <boost/corosio/native/detail/iocp/win_resolver_service.hpp>
25 #endif
26 #endif // !BOOST_COROSIO_MRDOCS
27
28 namespace boost::corosio {
29
30 /** An asynchronous DNS resolver with devirtualized operations.
31
32 This class template inherits from @ref resolver and shadows
33 the `resolve` operations with versions that call the backend
34 implementation directly, allowing the compiler to inline
35 through the entire call chain.
36
37 Non-async operations (`cancel`) remain unchanged and dispatch
38 through the compiled library.
39
40 A `native_resolver` IS-A `resolver` and can be passed to any
41 function expecting `resolver&`.
42
43 @tparam Backend A backend tag value (e.g., `epoll`).
44
45 @par Thread Safety
46 Same as @ref resolver.
47
48 @see resolver, epoll_t, iocp_t
49 */
50 template<auto Backend>
51 class native_resolver : public resolver
52 {
53 using backend_type = decltype(Backend);
54 using impl_type = typename backend_type::resolver_type;
55
56 2x impl_type& get_impl() noexcept
57 {
58 2x return *static_cast<impl_type*>(h_.get());
59 }
60
61 struct native_resolve_awaitable
62 {
63 native_resolver& self_;
64 std::string host_;
65 std::string service_;
66 resolve_flags flags_;
67 std::stop_token token_;
68 mutable std::error_code ec_;
69 mutable resolver_results results_;
70
71 2x native_resolve_awaitable(
72 native_resolver& self,
73 std::string_view host,
74 std::string_view service,
75 resolve_flags flags) noexcept
76 2x : self_(self)
77 4x , host_(host)
78 4x , service_(service)
79 2x , flags_(flags)
80 {
81 2x }
82
83 2x bool await_ready() const noexcept
84 {
85 2x return token_.stop_requested();
86 }
87
88 2x capy::io_result<resolver_results> await_resume() const noexcept
89 {
90 2x if (token_.stop_requested())
91 return {make_error_code(std::errc::operation_canceled), {}};
92 2x return {ec_, std::move(results_)};
93 }
94
95 2x auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
96 -> std::coroutine_handle<>
97 {
98 2x token_ = env->stop_token;
99 6x return self_.get_impl().resolve(
100 2x h, env->executor, host_, service_, flags_, token_, &ec_,
101 4x &results_);
102 }
103 };
104
105 struct native_reverse_awaitable
106 {
107 native_resolver& self_;
108 endpoint ep_;
109 reverse_flags flags_;
110 std::stop_token token_;
111 mutable std::error_code ec_;
112 mutable reverse_resolver_result result_;
113
114 native_reverse_awaitable(
115 native_resolver& self,
116 endpoint const& ep,
117 reverse_flags flags) noexcept
118 : self_(self)
119 , ep_(ep)
120 , flags_(flags)
121 {
122 }
123
124 bool await_ready() const noexcept
125 {
126 return token_.stop_requested();
127 }
128
129 capy::io_result<reverse_resolver_result> await_resume() const noexcept
130 {
131 if (token_.stop_requested())
132 return {make_error_code(std::errc::operation_canceled), {}};
133 return {ec_, std::move(result_)};
134 }
135
136 auto await_suspend(std::coroutine_handle<> h, capy::io_env const* env)
137 -> std::coroutine_handle<>
138 {
139 token_ = env->stop_token;
140 return self_.get_impl().reverse_resolve(
141 h, env->executor, ep_, flags_, token_, &ec_, &result_);
142 }
143 };
144
145 public:
146 /** Construct a native resolver from an execution context.
147
148 @param ctx The execution context that will own this resolver.
149 */
150 6x explicit native_resolver(capy::execution_context& ctx) : resolver(ctx) {}
151
152 /** Construct a native resolver from an executor.
153
154 @param ex The executor whose context will own the resolver.
155 */
156 template<class Ex>
157 requires(!std::same_as<std::remove_cvref_t<Ex>, native_resolver>) &&
158 capy::Executor<Ex>
159 explicit native_resolver(Ex const& ex) : native_resolver(ex.context())
160 {
161 }
162
163 /** Move construct.
164
165 @pre No awaitables returned by @p other's `resolve` methods
166 exist.
167 @pre The execution context associated with @p other must
168 outlive this resolver.
169 */
170 native_resolver(native_resolver&&) noexcept = default;
171
172 /** Move assign.
173
174 @pre No awaitables returned by either `*this` or the source's
175 `resolve` methods exist.
176 @pre The execution context associated with the source must
177 outlive this resolver.
178 */
179 native_resolver& operator=(native_resolver&&) noexcept = default;
180
181 native_resolver(native_resolver const&) = delete;
182 native_resolver& operator=(native_resolver const&) = delete;
183
184 /** Asynchronously resolve a host and service to endpoints.
185
186 Calls the backend implementation directly, bypassing virtual
187 dispatch. Otherwise identical to @ref resolver::resolve.
188
189 This resolver must outlive the returned awaitable.
190
191 @param host The host name or address string.
192 @param service The service name or port string.
193
194 @return An awaitable yielding `io_result<resolver_results>`.
195
196 @note `resolver_results` is an alias for `std::vector<resolver_entry>`;
197 copying it deep-copies every entry. See @ref resolver::resolve.
198 */
199 2x auto resolve(std::string_view host, std::string_view service)
200 {
201 return native_resolve_awaitable(
202 2x *this, host, service, resolve_flags::none);
203 }
204
205 /** Asynchronously resolve a host and service with flags.
206
207 This resolver must outlive the returned awaitable.
208
209 @param host The host name or address string.
210 @param service The service name or port string.
211 @param flags Flags controlling resolution behavior.
212
213 @return An awaitable yielding `io_result<resolver_results>`.
214 */
215 auto resolve(
216 std::string_view host, std::string_view service, resolve_flags flags)
217 {
218 return native_resolve_awaitable(*this, host, service, flags);
219 }
220
221 /** Asynchronously reverse-resolve an endpoint.
222
223 Calls the backend implementation directly, bypassing virtual
224 dispatch. Otherwise identical to the endpoint overload of
225 @ref resolver::resolve.
226
227 This resolver must outlive the returned awaitable.
228
229 @param ep The endpoint to resolve.
230
231 @return An awaitable yielding
232 `io_result<reverse_resolver_result>`.
233 */
234 auto resolve(endpoint const& ep)
235 {
236 return native_reverse_awaitable(*this, ep, reverse_flags::none);
237 }
238
239 /** Asynchronously reverse-resolve an endpoint with flags.
240
241 This resolver must outlive the returned awaitable.
242
243 @param ep The endpoint to resolve.
244 @param flags Flags controlling resolution behavior.
245
246 @return An awaitable yielding
247 `io_result<reverse_resolver_result>`.
248 */
249 auto resolve(endpoint const& ep, reverse_flags flags)
250 {
251 return native_reverse_awaitable(*this, ep, flags);
252 }
253 };
254
255 } // namespace boost::corosio
256
257 #endif
258