1 | // |
2 | // ip/basic_resolver_iterator.hpp |
3 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
4 | // |
5 | // Copyright (c) 2003-2015 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_ITERATOR_HPP |
12 | #define BOOST_ASIO_IP_BASIC_RESOLVER_ITERATOR_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 <iterator> |
22 | #include <string> |
23 | #include <vector> |
24 | #include <boost/asio/detail/shared_ptr.hpp> |
25 | #include <boost/asio/detail/socket_ops.hpp> |
26 | #include <boost/asio/detail/socket_types.hpp> |
27 | #include <boost/asio/ip/basic_resolver_entry.hpp> |
28 | |
29 | #if defined(BOOST_ASIO_WINDOWS_RUNTIME) |
30 | # include <boost/asio/detail/winrt_utils.hpp> |
31 | #endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) |
32 | |
33 | #include <boost/asio/detail/push_options.hpp> |
34 | |
35 | namespace boost { |
36 | namespace asio { |
37 | namespace ip { |
38 | |
39 | /// An iterator over the entries produced by a resolver. |
40 | /** |
41 | * The boost::asio::ip::basic_resolver_iterator class template is used to define |
42 | * iterators over the results returned by a resolver. |
43 | * |
44 | * The iterator's value_type, obtained when the iterator is dereferenced, is: |
45 | * @code const basic_resolver_entry<InternetProtocol> @endcode |
46 | * |
47 | * @par Thread Safety |
48 | * @e Distinct @e objects: Safe.@n |
49 | * @e Shared @e objects: Unsafe. |
50 | */ |
51 | template <typename InternetProtocol> |
52 | class basic_resolver_iterator |
53 | { |
54 | public: |
55 | /// The type used for the distance between two iterators. |
56 | typedef std::ptrdiff_t difference_type; |
57 | |
58 | /// The type of the value pointed to by the iterator. |
59 | typedef basic_resolver_entry<InternetProtocol> value_type; |
60 | |
61 | /// The type of the result of applying operator->() to the iterator. |
62 | typedef const basic_resolver_entry<InternetProtocol>* pointer; |
63 | |
64 | /// The type of the result of applying operator*() to the iterator. |
65 | typedef const basic_resolver_entry<InternetProtocol>& reference; |
66 | |
67 | /// The iterator category. |
68 | typedef std::forward_iterator_tag iterator_category; |
69 | |
70 | /// Default constructor creates an end iterator. |
71 | basic_resolver_iterator() |
72 | : index_(0) |
73 | { |
74 | } |
75 | |
76 | /// Create an iterator from an addrinfo list returned by getaddrinfo. |
77 | static basic_resolver_iterator create( |
78 | boost::asio::detail::addrinfo_type* address_info, |
79 | const std::string& host_name, const std::string& service_name) |
80 | { |
81 | basic_resolver_iterator iter; |
82 | if (!address_info) |
83 | return iter; |
84 | |
85 | std::string actual_host_name = host_name; |
86 | if (address_info->ai_canonname) |
87 | actual_host_name = address_info->ai_canonname; |
88 | |
89 | iter.values_.reset(new values_type); |
90 | |
91 | while (address_info) |
92 | { |
93 | if (address_info->ai_family == BOOST_ASIO_OS_DEF(AF_INET) |
94 | || address_info->ai_family == BOOST_ASIO_OS_DEF(AF_INET6)) |
95 | { |
96 | using namespace std; // For memcpy. |
97 | typename InternetProtocol::endpoint endpoint; |
98 | endpoint.resize(static_cast<std::size_t>(address_info->ai_addrlen)); |
99 | memcpy(endpoint.data(), address_info->ai_addr, |
100 | address_info->ai_addrlen); |
101 | iter.values_->push_back( |
102 | basic_resolver_entry<InternetProtocol>(endpoint, |
103 | actual_host_name, service_name)); |
104 | } |
105 | address_info = address_info->ai_next; |
106 | } |
107 | |
108 | return iter; |
109 | } |
110 | |
111 | /// Create an iterator from an endpoint, host name and service name. |
112 | static basic_resolver_iterator create( |
113 | const typename InternetProtocol::endpoint& endpoint, |
114 | const std::string& host_name, const std::string& service_name) |
115 | { |
116 | basic_resolver_iterator iter; |
117 | iter.values_.reset(new values_type); |
118 | iter.values_->push_back( |
119 | basic_resolver_entry<InternetProtocol>( |
120 | endpoint, host_name, service_name)); |
121 | return iter; |
122 | } |
123 | |
124 | /// Create an iterator from a sequence of endpoints, host and service name. |
125 | template <typename EndpointIterator> |
126 | static basic_resolver_iterator create( |
127 | EndpointIterator begin, EndpointIterator end, |
128 | const std::string& host_name, const std::string& service_name) |
129 | { |
130 | basic_resolver_iterator iter; |
131 | if (begin != end) |
132 | { |
133 | iter.values_.reset(new values_type); |
134 | for (EndpointIterator ep_iter = begin; ep_iter != end; ++ep_iter) |
135 | { |
136 | iter.values_->push_back( |
137 | basic_resolver_entry<InternetProtocol>( |
138 | *ep_iter, host_name, service_name)); |
139 | } |
140 | } |
141 | return iter; |
142 | } |
143 | |
144 | #if defined(BOOST_ASIO_WINDOWS_RUNTIME) |
145 | /// Create an iterator from a Windows Runtime list of EndpointPair objects. |
146 | static basic_resolver_iterator create( |
147 | Windows::Foundation::Collections::IVectorView< |
148 | Windows::Networking::EndpointPair^>^ endpoints, |
149 | const boost::asio::detail::addrinfo_type& hints, |
150 | const std::string& host_name, const std::string& service_name) |
151 | { |
152 | basic_resolver_iterator iter; |
153 | if (endpoints->Size) |
154 | { |
155 | iter.values_.reset(new values_type); |
156 | for (unsigned int i = 0; i < endpoints->Size; ++i) |
157 | { |
158 | auto pair = endpoints->GetAt(i); |
159 | |
160 | if (hints.ai_family == BOOST_ASIO_OS_DEF(AF_INET) |
161 | && pair->RemoteHostName->Type |
162 | != Windows::Networking::HostNameType::Ipv4) |
163 | continue; |
164 | |
165 | if (hints.ai_family == BOOST_ASIO_OS_DEF(AF_INET6) |
166 | && pair->RemoteHostName->Type |
167 | != Windows::Networking::HostNameType::Ipv6) |
168 | continue; |
169 | |
170 | iter.values_->push_back( |
171 | basic_resolver_entry<InternetProtocol>( |
172 | typename InternetProtocol::endpoint( |
173 | ip::address::from_string( |
174 | boost::asio::detail::winrt_utils::string( |
175 | pair->RemoteHostName->CanonicalName)), |
176 | boost::asio::detail::winrt_utils::integer( |
177 | pair->RemoteServiceName)), |
178 | host_name, service_name)); |
179 | } |
180 | } |
181 | return iter; |
182 | } |
183 | #endif // defined(BOOST_ASIO_WINDOWS_RUNTIME) |
184 | |
185 | /// Dereference an iterator. |
186 | const basic_resolver_entry<InternetProtocol>& operator*() const |
187 | { |
188 | return dereference(); |
189 | } |
190 | |
191 | /// Dereference an iterator. |
192 | const basic_resolver_entry<InternetProtocol>* operator->() const |
193 | { |
194 | return &dereference(); |
195 | } |
196 | |
197 | /// Increment operator (prefix). |
198 | basic_resolver_iterator& operator++() |
199 | { |
200 | increment(); |
201 | return *this; |
202 | } |
203 | |
204 | /// Increment operator (postfix). |
205 | basic_resolver_iterator operator++(int) |
206 | { |
207 | basic_resolver_iterator tmp(*this); |
208 | ++*this; |
209 | return tmp; |
210 | } |
211 | |
212 | /// Test two iterators for equality. |
213 | friend bool operator==(const basic_resolver_iterator& a, |
214 | const basic_resolver_iterator& b) |
215 | { |
216 | return a.equal(b); |
217 | } |
218 | |
219 | /// Test two iterators for inequality. |
220 | friend bool operator!=(const basic_resolver_iterator& a, |
221 | const basic_resolver_iterator& b) |
222 | { |
223 | return !a.equal(b); |
224 | } |
225 | |
226 | private: |
227 | void increment() |
228 | { |
229 | if (++index_ == values_->size()) |
230 | { |
231 | // Reset state to match a default constructed end iterator. |
232 | values_.reset(); |
233 | index_ = 0; |
234 | } |
235 | } |
236 | |
237 | bool equal(const basic_resolver_iterator& other) const |
238 | { |
239 | if (!values_ && !other.values_) |
240 | return true; |
241 | if (values_ != other.values_) |
242 | return false; |
243 | return index_ == other.index_; |
244 | } |
245 | |
246 | const basic_resolver_entry<InternetProtocol>& dereference() const |
247 | { |
248 | return (*values_)[index_]; |
249 | } |
250 | |
251 | typedef std::vector<basic_resolver_entry<InternetProtocol> > values_type; |
252 | boost::asio::detail::shared_ptr<values_type> values_; |
253 | std::size_t index_; |
254 | }; |
255 | |
256 | } // namespace ip |
257 | } // namespace asio |
258 | } // namespace boost |
259 | |
260 | #include <boost/asio/detail/pop_options.hpp> |
261 | |
262 | #endif // BOOST_ASIO_IP_BASIC_RESOLVER_ITERATOR_HPP |
263 | |