1 | // |
2 | // ip/basic_resolver_results.hpp |
3 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
4 | // |
5 | // Copyright (c) 2003-2024 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_IP_BASIC_RESOLVER_RESULTS_HPP |
12 | #define BOOST_ASIO_IP_BASIC_RESOLVER_RESULTS_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 | #include <cstddef> |
20 | #include <cstring> |
21 | #include <boost/asio/detail/socket_ops.hpp> |
22 | #include <boost/asio/detail/socket_types.hpp> |
23 | #include <boost/asio/ip/basic_resolver_iterator.hpp> |
24 | |
25 | #if defined(BOOST_ASIO_WINDOWS_RUNTIME) |
26 | # include <boost/asio/detail/winrt_utils.hpp> |
27 | #endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) |
28 | |
29 | #include <boost/asio/detail/push_options.hpp> |
30 | |
31 | namespace boost { |
32 | namespace asio { |
33 | namespace ip { |
34 | |
35 | /// A range of entries produced by a resolver. |
36 | /** |
37 | * The boost::asio::ip::basic_resolver_results class template is used to define |
38 | * a range over the results returned by a resolver. |
39 | * |
40 | * The iterator's value_type, obtained when a results iterator is dereferenced, |
41 | * is: @code const basic_resolver_entry<InternetProtocol> @endcode |
42 | * |
43 | * @note For backward compatibility, basic_resolver_results is derived from |
44 | * basic_resolver_iterator. This derivation is deprecated. |
45 | * |
46 | * @par Thread Safety |
47 | * @e Distinct @e objects: Safe.@n |
48 | * @e Shared @e objects: Unsafe. |
49 | */ |
50 | template <typename InternetProtocol> |
51 | class basic_resolver_results |
52 | #if !defined(BOOST_ASIO_NO_DEPRECATED) |
53 | : public basic_resolver_iterator<InternetProtocol> |
54 | #else // !defined(BOOST_ASIO_NO_DEPRECATED) |
55 | : private basic_resolver_iterator<InternetProtocol> |
56 | #endif // !defined(BOOST_ASIO_NO_DEPRECATED) |
57 | { |
58 | public: |
59 | /// The protocol type associated with the results. |
60 | typedef InternetProtocol protocol_type; |
61 | |
62 | /// The endpoint type associated with the results. |
63 | typedef typename protocol_type::endpoint endpoint_type; |
64 | |
65 | /// The type of a value in the results range. |
66 | typedef basic_resolver_entry<protocol_type> value_type; |
67 | |
68 | /// The type of a const reference to a value in the range. |
69 | typedef const value_type& const_reference; |
70 | |
71 | /// The type of a non-const reference to a value in the range. |
72 | typedef value_type& reference; |
73 | |
74 | /// The type of an iterator into the range. |
75 | typedef basic_resolver_iterator<protocol_type> const_iterator; |
76 | |
77 | /// The type of an iterator into the range. |
78 | typedef const_iterator iterator; |
79 | |
80 | /// Type used to represent the distance between two iterators in the range. |
81 | typedef std::ptrdiff_t difference_type; |
82 | |
83 | /// Type used to represent a count of the elements in the range. |
84 | typedef std::size_t size_type; |
85 | |
86 | /// Default constructor creates an empty range. |
87 | basic_resolver_results() |
88 | { |
89 | } |
90 | |
91 | /// Copy constructor. |
92 | basic_resolver_results(const basic_resolver_results& other) |
93 | : basic_resolver_iterator<InternetProtocol>(other) |
94 | { |
95 | } |
96 | |
97 | /// Move constructor. |
98 | basic_resolver_results(basic_resolver_results&& other) |
99 | : basic_resolver_iterator<InternetProtocol>( |
100 | static_cast<basic_resolver_results&&>(other)) |
101 | { |
102 | } |
103 | |
104 | /// Assignment operator. |
105 | basic_resolver_results& operator=(const basic_resolver_results& other) |
106 | { |
107 | basic_resolver_iterator<InternetProtocol>::operator=(other); |
108 | return *this; |
109 | } |
110 | |
111 | /// Move-assignment operator. |
112 | basic_resolver_results& operator=(basic_resolver_results&& other) |
113 | { |
114 | basic_resolver_iterator<InternetProtocol>::operator=( |
115 | static_cast<basic_resolver_results&&>(other)); |
116 | return *this; |
117 | } |
118 | |
119 | #if !defined(GENERATING_DOCUMENTATION) |
120 | // Create results from an addrinfo list returned by getaddrinfo. |
121 | static basic_resolver_results create( |
122 | boost::asio::detail::addrinfo_type* address_info, |
123 | const std::string& host_name, const std::string& service_name) |
124 | { |
125 | basic_resolver_results results; |
126 | if (!address_info) |
127 | return results; |
128 | |
129 | std::string actual_host_name = host_name; |
130 | if (address_info->ai_canonname) |
131 | actual_host_name = address_info->ai_canonname; |
132 | |
133 | results.values_.reset(new values_type); |
134 | |
135 | while (address_info) |
136 | { |
137 | if (address_info->ai_family == BOOST_ASIO_OS_DEF(AF_INET) |
138 | || address_info->ai_family == BOOST_ASIO_OS_DEF(AF_INET6)) |
139 | { |
140 | using namespace std; // For memcpy. |
141 | typename InternetProtocol::endpoint endpoint; |
142 | endpoint.resize(static_cast<std::size_t>(address_info->ai_addrlen)); |
143 | memcpy(endpoint.data(), address_info->ai_addr, |
144 | address_info->ai_addrlen); |
145 | results.values_->push_back( |
146 | basic_resolver_entry<InternetProtocol>(endpoint, |
147 | actual_host_name, service_name)); |
148 | } |
149 | address_info = address_info->ai_next; |
150 | } |
151 | |
152 | return results; |
153 | } |
154 | |
155 | // Create results from an endpoint, host name and service name. |
156 | static basic_resolver_results create(const endpoint_type& endpoint, |
157 | const std::string& host_name, const std::string& service_name) |
158 | { |
159 | basic_resolver_results results; |
160 | results.values_.reset(new values_type); |
161 | results.values_->push_back( |
162 | basic_resolver_entry<InternetProtocol>( |
163 | endpoint, host_name, service_name)); |
164 | return results; |
165 | } |
166 | |
167 | // Create results from a sequence of endpoints, host and service name. |
168 | template <typename EndpointIterator> |
169 | static basic_resolver_results create( |
170 | EndpointIterator begin, EndpointIterator end, |
171 | const std::string& host_name, const std::string& service_name) |
172 | { |
173 | basic_resolver_results results; |
174 | if (begin != end) |
175 | { |
176 | results.values_.reset(new values_type); |
177 | for (EndpointIterator ep_iter = begin; ep_iter != end; ++ep_iter) |
178 | { |
179 | results.values_->push_back( |
180 | basic_resolver_entry<InternetProtocol>( |
181 | *ep_iter, host_name, service_name)); |
182 | } |
183 | } |
184 | return results; |
185 | } |
186 | |
187 | # if defined(BOOST_ASIO_WINDOWS_RUNTIME) |
188 | // Create results from a Windows Runtime list of EndpointPair objects. |
189 | static basic_resolver_results create( |
190 | Windows::Foundation::Collections::IVectorView< |
191 | Windows::Networking::EndpointPair^>^ endpoints, |
192 | const boost::asio::detail::addrinfo_type& hints, |
193 | const std::string& host_name, const std::string& service_name) |
194 | { |
195 | basic_resolver_results results; |
196 | if (endpoints->Size) |
197 | { |
198 | results.values_.reset(new values_type); |
199 | for (unsigned int i = 0; i < endpoints->Size; ++i) |
200 | { |
201 | auto pair = endpoints->GetAt(i); |
202 | |
203 | if (hints.ai_family == BOOST_ASIO_OS_DEF(AF_INET) |
204 | && pair->RemoteHostName->Type |
205 | != Windows::Networking::HostNameType::Ipv4) |
206 | continue; |
207 | |
208 | if (hints.ai_family == BOOST_ASIO_OS_DEF(AF_INET6) |
209 | && pair->RemoteHostName->Type |
210 | != Windows::Networking::HostNameType::Ipv6) |
211 | continue; |
212 | |
213 | results.values_->push_back( |
214 | basic_resolver_entry<InternetProtocol>( |
215 | typename InternetProtocol::endpoint( |
216 | ip::make_address( |
217 | boost::asio::detail::winrt_utils::string( |
218 | pair->RemoteHostName->CanonicalName)), |
219 | boost::asio::detail::winrt_utils::integer( |
220 | pair->RemoteServiceName)), |
221 | host_name, service_name)); |
222 | } |
223 | } |
224 | return results; |
225 | } |
226 | # endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) |
227 | #endif // !defined(GENERATING_DOCUMENTATION) |
228 | |
229 | /// Get the number of entries in the results range. |
230 | size_type size() const noexcept |
231 | { |
232 | return this->values_ ? this->values_->size() : 0; |
233 | } |
234 | |
235 | /// Get the maximum number of entries permitted in a results range. |
236 | size_type max_size() const noexcept |
237 | { |
238 | return this->values_ ? this->values_->max_size() : values_type().max_size(); |
239 | } |
240 | |
241 | /// Determine whether the results range is empty. |
242 | bool empty() const noexcept |
243 | { |
244 | return this->values_ ? this->values_->empty() : true; |
245 | } |
246 | |
247 | /// Obtain a begin iterator for the results range. |
248 | const_iterator begin() const |
249 | { |
250 | basic_resolver_results tmp(*this); |
251 | tmp.index_ = 0; |
252 | return static_cast<basic_resolver_results&&>(tmp); |
253 | } |
254 | |
255 | /// Obtain an end iterator for the results range. |
256 | const_iterator end() const |
257 | { |
258 | return const_iterator(); |
259 | } |
260 | |
261 | /// Obtain a begin iterator for the results range. |
262 | const_iterator cbegin() const |
263 | { |
264 | return begin(); |
265 | } |
266 | |
267 | /// Obtain an end iterator for the results range. |
268 | const_iterator cend() const |
269 | { |
270 | return end(); |
271 | } |
272 | |
273 | /// Swap the results range with another. |
274 | void swap(basic_resolver_results& that) noexcept |
275 | { |
276 | if (this != &that) |
277 | { |
278 | this->values_.swap(that.values_); |
279 | std::size_t index = this->index_; |
280 | this->index_ = that.index_; |
281 | that.index_ = index; |
282 | } |
283 | } |
284 | |
285 | /// Test two iterators for equality. |
286 | friend bool operator==(const basic_resolver_results& a, |
287 | const basic_resolver_results& b) |
288 | { |
289 | return a.equal(b); |
290 | } |
291 | |
292 | /// Test two iterators for inequality. |
293 | friend bool operator!=(const basic_resolver_results& a, |
294 | const basic_resolver_results& b) |
295 | { |
296 | return !a.equal(b); |
297 | } |
298 | |
299 | private: |
300 | typedef std::vector<basic_resolver_entry<InternetProtocol>> values_type; |
301 | }; |
302 | |
303 | } // namespace ip |
304 | } // namespace asio |
305 | } // namespace boost |
306 | |
307 | #include <boost/asio/detail/pop_options.hpp> |
308 | |
309 | #endif // BOOST_ASIO_IP_BASIC_RESOLVER_RESULTS_HPP |
310 | |