TLA Line data 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 : #include <boost/corosio/detail/op_base.hpp>
17 :
18 : #ifndef BOOST_COROSIO_MRDOCS
19 : #if BOOST_COROSIO_HAS_EPOLL || BOOST_COROSIO_HAS_SELECT || \
20 : BOOST_COROSIO_HAS_KQUEUE
21 : #include <boost/corosio/native/detail/posix/posix_resolver_service.hpp>
22 : #endif
23 :
24 : #if BOOST_COROSIO_HAS_IOCP
25 : #include <boost/corosio/native/detail/iocp/win_resolver_service.hpp>
26 : #endif
27 : #endif // !BOOST_COROSIO_MRDOCS
28 :
29 : namespace boost::corosio {
30 :
31 : /** An asynchronous DNS resolver with devirtualized operations.
32 :
33 : This class template inherits from @ref resolver and shadows
34 : the `resolve` operations with versions that call the backend
35 : implementation directly, allowing the compiler to inline
36 : through the entire call chain.
37 :
38 : Non-async operations (`cancel`) remain unchanged and dispatch
39 : through the compiled library.
40 :
41 : A `native_resolver` IS-A `resolver` and can be passed to any
42 : function expecting `resolver&`.
43 :
44 : @tparam Backend A backend tag value (e.g., `epoll`).
45 :
46 : @par Thread Safety
47 : Same as @ref resolver.
48 :
49 : @see resolver, epoll_t, iocp_t
50 : */
51 : template<auto Backend>
52 : class native_resolver : public resolver
53 : {
54 : using backend_type = decltype(Backend);
55 : using impl_type = typename backend_type::resolver_type;
56 :
57 HIT 2 : impl_type& get_impl() noexcept
58 : {
59 2 : return *static_cast<impl_type*>(h_.get());
60 : }
61 :
62 : struct native_resolve_awaitable
63 : : detail::value_op_base<native_resolve_awaitable, resolver_results>
64 : {
65 : native_resolver& self_;
66 : std::string host_;
67 : std::string service_;
68 : resolve_flags flags_;
69 :
70 4 : native_resolve_awaitable(
71 : native_resolver& self,
72 : std::string_view host,
73 : std::string_view service,
74 : resolve_flags flags) noexcept
75 4 : : self_(self)
76 8 : , host_(host)
77 8 : , service_(service)
78 4 : , flags_(flags)
79 : {
80 4 : }
81 :
82 : std::coroutine_handle<>
83 2 : dispatch(std::coroutine_handle<> h, capy::executor_ref ex) const
84 : {
85 6 : return self_.get_impl().resolve(
86 2 : h, ex, host_, service_, flags_, this->token_, &this->ec_,
87 4 : &this->value_);
88 : }
89 : };
90 :
91 : struct native_reverse_awaitable
92 : : detail::
93 : value_op_base<native_reverse_awaitable, reverse_resolver_result>
94 : {
95 : native_resolver& self_;
96 : endpoint ep_;
97 : reverse_flags flags_;
98 :
99 : native_reverse_awaitable(
100 : native_resolver& self,
101 : endpoint const& ep,
102 : reverse_flags flags) noexcept
103 : : self_(self)
104 : , ep_(ep)
105 : , flags_(flags)
106 : {
107 : }
108 :
109 : std::coroutine_handle<>
110 : dispatch(std::coroutine_handle<> h, capy::executor_ref ex) const
111 : {
112 : return self_.get_impl().reverse_resolve(
113 : h, ex, ep_, flags_, this->token_, &this->ec_, &this->value_);
114 : }
115 : };
116 :
117 : public:
118 : /** Construct a native resolver from an execution context.
119 :
120 : @param ctx The execution context that will own this resolver.
121 : */
122 8 : explicit native_resolver(capy::execution_context& ctx) : resolver(ctx) {}
123 :
124 : /** Construct a native resolver from an executor.
125 :
126 : @param ex The executor whose context will own the resolver.
127 : */
128 : template<class Ex>
129 : requires(!std::same_as<std::remove_cvref_t<Ex>, native_resolver>) &&
130 : capy::Executor<Ex>
131 : explicit native_resolver(Ex const& ex) : native_resolver(ex.context())
132 : {
133 : }
134 :
135 : /** Move construct.
136 :
137 : @pre No awaitables returned by @p other's `resolve` methods
138 : exist.
139 : @pre The execution context associated with @p other must
140 : outlive this resolver.
141 : */
142 : native_resolver(native_resolver&&) noexcept = default;
143 :
144 : /** Move assign.
145 :
146 : @pre No awaitables returned by either `*this` or the source's
147 : `resolve` methods exist.
148 : @pre The execution context associated with the source must
149 : outlive this resolver.
150 : */
151 : native_resolver& operator=(native_resolver&&) noexcept = default;
152 :
153 : native_resolver(native_resolver const&) = delete;
154 : native_resolver& operator=(native_resolver const&) = delete;
155 :
156 : /** Asynchronously resolve a host and service to endpoints.
157 :
158 : Calls the backend implementation directly, bypassing virtual
159 : dispatch. Otherwise identical to @ref resolver::resolve.
160 :
161 : This resolver must outlive the returned awaitable.
162 :
163 : @param host The host name or address string.
164 : @param service The service name or port string.
165 :
166 : @return An awaitable yielding `io_result<resolver_results>`.
167 :
168 : @note `resolver_results` is an alias for `std::vector<resolver_entry>`;
169 : copying it deep-copies every entry. See @ref resolver::resolve.
170 : */
171 4 : [[nodiscard]] auto resolve(std::string_view host, std::string_view service)
172 : {
173 : return native_resolve_awaitable(
174 4 : *this, host, service, resolve_flags::none);
175 : }
176 :
177 : /** Asynchronously resolve a host and service with flags.
178 :
179 : This resolver must outlive the returned awaitable.
180 :
181 : @param host The host name or address string.
182 : @param service The service name or port string.
183 : @param flags Flags controlling resolution behavior.
184 :
185 : @return An awaitable yielding `io_result<resolver_results>`.
186 : */
187 : [[nodiscard]] auto resolve(
188 : std::string_view host, std::string_view service, resolve_flags flags)
189 : {
190 : return native_resolve_awaitable(*this, host, service, flags);
191 : }
192 :
193 : /** Asynchronously reverse-resolve an endpoint.
194 :
195 : Calls the backend implementation directly, bypassing virtual
196 : dispatch. Otherwise identical to the endpoint overload of
197 : @ref resolver::resolve.
198 :
199 : This resolver must outlive the returned awaitable.
200 :
201 : @param ep The endpoint to resolve.
202 :
203 : @return An awaitable yielding
204 : `io_result<reverse_resolver_result>`.
205 : */
206 : [[nodiscard]] auto resolve(endpoint const& ep)
207 : {
208 : return native_reverse_awaitable(*this, ep, reverse_flags::none);
209 : }
210 :
211 : /** Asynchronously reverse-resolve an endpoint with flags.
212 :
213 : This resolver must outlive the returned awaitable.
214 :
215 : @param ep The endpoint to resolve.
216 : @param flags Flags controlling resolution behavior.
217 :
218 : @return An awaitable yielding
219 : `io_result<reverse_resolver_result>`.
220 : */
221 : [[nodiscard]] auto resolve(endpoint const& ep, reverse_flags flags)
222 : {
223 : return native_reverse_awaitable(*this, ep, flags);
224 : }
225 : };
226 :
227 : } // namespace boost::corosio
228 :
229 : #endif
|