]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // ip/basic_resolver_iterator.hpp | |
3 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
4 | // | |
5 | // Copyright (c) 2003-2016 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 |