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