1 // 2 // detail/resolver_service.hpp 3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) 6 // 7 // Distributed under the Boost Software License, Version 1.0. (See accompanying 8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 // 10 11 #ifndef BOOST_ASIO_DETAIL_RESOLVER_SERVICE_HPP 12 #define BOOST_ASIO_DETAIL_RESOLVER_SERVICE_HPP 13 14 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 15 # pragma once 16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 17 18 #include <boost/asio/detail/config.hpp> 19 20 #if !defined(BOOST_ASIO_WINDOWS_RUNTIME) 21 22 #include <boost/asio/ip/basic_resolver_query.hpp> 23 #include <boost/asio/ip/basic_resolver_results.hpp> 24 #include <boost/asio/detail/concurrency_hint.hpp> 25 #include <boost/asio/detail/memory.hpp> 26 #include <boost/asio/detail/resolve_endpoint_op.hpp> 27 #include <boost/asio/detail/resolve_query_op.hpp> 28 #include <boost/asio/detail/resolver_service_base.hpp> 29 30 #include <boost/asio/detail/push_options.hpp> 31 32 namespace boost { 33 namespace asio { 34 namespace detail { 35 36 template <typename Protocol> 37 class resolver_service : 38 public execution_context_service_base<resolver_service<Protocol> >, 39 public resolver_service_base 40 { 41 public: 42 // The implementation type of the resolver. A cancellation token is used to 43 // indicate to the background thread that the operation has been cancelled. 44 typedef socket_ops::shared_cancel_token_type implementation_type; 45 46 // The endpoint type. 47 typedef typename Protocol::endpoint endpoint_type; 48 49 // The query type. 50 typedef boost::asio::ip::basic_resolver_query<Protocol> query_type; 51 52 // The results type. 53 typedef boost::asio::ip::basic_resolver_results<Protocol> results_type; 54 55 // Constructor. resolver_service(execution_context & context)56 resolver_service(execution_context& context) 57 : execution_context_service_base<resolver_service<Protocol> >(context), 58 resolver_service_base(context) 59 { 60 } 61 62 // Destroy all user-defined handler objects owned by the service. shutdown()63 void shutdown() 64 { 65 this->base_shutdown(); 66 } 67 68 // Perform any fork-related housekeeping. notify_fork(execution_context::fork_event fork_ev)69 void notify_fork(execution_context::fork_event fork_ev) 70 { 71 this->base_notify_fork(fork_ev); 72 } 73 74 // Resolve a query to a list of entries. resolve(implementation_type &,const query_type & qry,boost::system::error_code & ec)75 results_type resolve(implementation_type&, const query_type& qry, 76 boost::system::error_code& ec) 77 { 78 boost::asio::detail::addrinfo_type* address_info = 0; 79 80 socket_ops::getaddrinfo(qry.host_name().c_str(), 81 qry.service_name().c_str(), qry.hints(), &address_info, ec); 82 auto_addrinfo auto_address_info(address_info); 83 84 return ec ? results_type() : results_type::create( 85 address_info, qry.host_name(), qry.service_name()); 86 } 87 88 // Asynchronously resolve a query to a list of entries. 89 template <typename Handler, typename IoExecutor> async_resolve(implementation_type & impl,const query_type & qry,Handler & handler,const IoExecutor & io_ex)90 void async_resolve(implementation_type& impl, const query_type& qry, 91 Handler& handler, const IoExecutor& io_ex) 92 { 93 // Allocate and construct an operation to wrap the handler. 94 typedef resolve_query_op<Protocol, Handler, IoExecutor> op; 95 typename op::ptr p = { boost::asio::detail::addressof(handler), 96 op::ptr::allocate(handler), 0 }; 97 p.p = new (p.v) op(impl, qry, scheduler_, handler, io_ex); 98 99 BOOST_ASIO_HANDLER_CREATION((scheduler_.context(), 100 *p.p, "resolver", &impl, 0, "async_resolve")); 101 102 start_resolve_op(p.p); 103 p.v = p.p = 0; 104 } 105 106 // Resolve an endpoint to a list of entries. resolve(implementation_type &,const endpoint_type & endpoint,boost::system::error_code & ec)107 results_type resolve(implementation_type&, 108 const endpoint_type& endpoint, boost::system::error_code& ec) 109 { 110 char host_name[NI_MAXHOST]; 111 char service_name[NI_MAXSERV]; 112 socket_ops::sync_getnameinfo(endpoint.data(), endpoint.size(), 113 host_name, NI_MAXHOST, service_name, NI_MAXSERV, 114 endpoint.protocol().type(), ec); 115 116 return ec ? results_type() : results_type::create( 117 endpoint, host_name, service_name); 118 } 119 120 // Asynchronously resolve an endpoint to a list of entries. 121 template <typename Handler, typename IoExecutor> async_resolve(implementation_type & impl,const endpoint_type & endpoint,Handler & handler,const IoExecutor & io_ex)122 void async_resolve(implementation_type& impl, const endpoint_type& endpoint, 123 Handler& handler, const IoExecutor& io_ex) 124 { 125 // Allocate and construct an operation to wrap the handler. 126 typedef resolve_endpoint_op<Protocol, Handler, IoExecutor> op; 127 typename op::ptr p = { boost::asio::detail::addressof(handler), 128 op::ptr::allocate(handler), 0 }; 129 p.p = new (p.v) op(impl, endpoint, scheduler_, handler, io_ex); 130 131 BOOST_ASIO_HANDLER_CREATION((scheduler_.context(), 132 *p.p, "resolver", &impl, 0, "async_resolve")); 133 134 start_resolve_op(p.p); 135 p.v = p.p = 0; 136 } 137 }; 138 139 } // namespace detail 140 } // namespace asio 141 } // namespace boost 142 143 #include <boost/asio/detail/pop_options.hpp> 144 145 #endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME) 146 147 #endif // BOOST_ASIO_DETAIL_RESOLVER_SERVICE_HPP 148