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