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 - /** An asynchronous DNS resolver with devirtualized operations. 31 + /** Resolves host names to endpoints, calling the backend directly.
32   32  
33 - This class template inherits from @ref resolver and shadows 33 + This class template inherits from @ref resolver. It shadows the
34 - the `resolve` operations with versions that call the backend 34 + `resolve` operations with versions that call the backend
35 - implementation directly, allowing the compiler to inline 35 + implementation directly. The compiler can then inline through the
36 - through the entire call chain. 36 + 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 will own this resolver. 119 + @param ctx The execution context that owns 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 will own the resolver. 125 + @param ex The executor whose context owns 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 @p other's `resolve` methods 136 + @pre No awaitables returned by the source's `resolve` methods
137   exist. 137   exist.
138 - @pre The execution context associated with @p other must 138 + @pre The execution context associated with the source 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   144  
  145 + @return Reference to this resolver.
  146 +
145   @pre No awaitables returned by either `*this` or the source's 147   @pre No awaitables returned by either `*this` or the source's
146   `resolve` methods exist. 148   `resolve` methods exist.
147   @pre The execution context associated with the source must 149   @pre The execution context associated with the source must
148   outlive this resolver. 150   outlive this resolver.
149   */ 151   */
150   native_resolver& operator=(native_resolver&&) noexcept = default; 152   native_resolver& operator=(native_resolver&&) noexcept = default;
151   153  
152 - native_resolver(native_resolver const&) = delete; 154 + /// Copy construction is disabled; the handle is uniquely owned.
  155 + native_resolver(native_resolver const&) = delete;
  156 + /// Copy assignment is disabled; the handle is uniquely owned.
153   native_resolver& operator=(native_resolver const&) = delete; 157   native_resolver& operator=(native_resolver const&) = delete;
154   158  
155   /** Asynchronously resolve a host and service to endpoints. 159   /** Asynchronously resolve a host and service to endpoints.
156   160  
157   Calls the backend implementation directly, bypassing virtual 161   Calls the backend implementation directly, bypassing virtual
158   dispatch. Otherwise identical to @ref resolver::resolve. 162   dispatch. Otherwise identical to @ref resolver::resolve.
159   163  
160   This resolver must outlive the returned awaitable. 164   This resolver must outlive the returned awaitable.
161   165  
162   @param host The host name or address string. 166   @param host The host name or address string.
163   @param service The service name or port string. 167   @param service The service name or port string.
164   168  
165   @return An awaitable yielding `io_result<std::vector<endpoint>>`. 169   @return An awaitable yielding `io_result<std::vector<endpoint>>`.
166   */ 170   */
HITCBC 167   4 [[nodiscard]] auto resolve(std::string_view host, std::string_view service) 171   4 [[nodiscard]] auto resolve(std::string_view host, std::string_view service)
168   { 172   {
169   return native_resolve_awaitable( 173   return native_resolve_awaitable(
HITCBC 170   4 *this, host, service, resolve_flags::none); 174   4 *this, host, service, resolve_flags::none);
171   } 175   }
172   176  
173   /** Asynchronously resolve a host and service with flags. 177   /** Asynchronously resolve a host and service with flags.
174   178  
175   This resolver must outlive the returned awaitable. 179   This resolver must outlive the returned awaitable.
176   180  
177   @param host The host name or address string. 181   @param host The host name or address string.
178   @param service The service name or port string. 182   @param service The service name or port string.
179   @param flags Flags controlling resolution behavior. 183   @param flags Flags controlling resolution behavior.
180   184  
181   @return An awaitable yielding 185   @return An awaitable yielding
182   `io_result<std::vector<endpoint>>`. 186   `io_result<std::vector<endpoint>>`.
183   */ 187   */
184   [[nodiscard]] auto resolve( 188   [[nodiscard]] auto resolve(
185   std::string_view host, std::string_view service, resolve_flags flags) 189   std::string_view host, std::string_view service, resolve_flags flags)
186   { 190   {
187   return native_resolve_awaitable(*this, host, service, flags); 191   return native_resolve_awaitable(*this, host, service, flags);
188   } 192   }
189   193  
190   /** Asynchronously reverse-resolve an endpoint. 194   /** Asynchronously reverse-resolve an endpoint.
191   195  
192   Calls the backend implementation directly, bypassing virtual 196   Calls the backend implementation directly, bypassing virtual
193   dispatch. Otherwise identical to the endpoint overload of 197   dispatch. Otherwise identical to the endpoint overload of
194   @ref resolver::resolve. 198   @ref resolver::resolve.
195   199  
196   This resolver must outlive the returned awaitable. 200   This resolver must outlive the returned awaitable.
197   201  
198   @param ep The endpoint to resolve. 202   @param ep The endpoint to resolve.
199   203  
200   @return An awaitable yielding 204   @return An awaitable yielding
201   `io_result<endpoint_name>`. 205   `io_result<endpoint_name>`.
202   */ 206   */
203   [[nodiscard]] auto resolve(endpoint const& ep) 207   [[nodiscard]] auto resolve(endpoint const& ep)
204   { 208   {
205   return native_reverse_awaitable(*this, ep, reverse_flags::none); 209   return native_reverse_awaitable(*this, ep, reverse_flags::none);
206   } 210   }
207   211  
208   /** Asynchronously reverse-resolve an endpoint with flags. 212   /** Asynchronously reverse-resolve an endpoint with flags.
209   213  
210   This resolver must outlive the returned awaitable. 214   This resolver must outlive the returned awaitable.
211   215  
212   @param ep The endpoint to resolve. 216   @param ep The endpoint to resolve.
213   @param flags Flags controlling resolution behavior. 217   @param flags Flags controlling resolution behavior.
214   218  
215   @return An awaitable yielding 219   @return An awaitable yielding
216   `io_result<endpoint_name>`. 220   `io_result<endpoint_name>`.
217   */ 221   */
218   [[nodiscard]] auto resolve(endpoint const& ep, reverse_flags flags) 222   [[nodiscard]] auto resolve(endpoint const& ep, reverse_flags flags)
219   { 223   {
220   return native_reverse_awaitable(*this, ep, flags); 224   return native_reverse_awaitable(*this, ep, flags);
221   } 225   }
222   }; 226   };
223   227  
224   } // namespace boost::corosio 228   } // namespace boost::corosio
225   229  
226   #endif 230   #endif