neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
resolver.hpp
Go to the documentation of this file.
1// resolver.hpp
2/*
3 * Copyright (c) 2007 Leigh Johnston.
4 *
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * * Neither the name of Leigh Johnston nor the names of any
19 * other contributors to this software may be used to endorse or
20 * promote products derived from this software without specific prior
21 * written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
24 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
25 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*/
35
36#pragma once
37
38#include <neolib/neolib.hpp>
39#include <stdexcept>
40#include <vector>
41#include <memory>
42#include <boost/bind.hpp>
43#include <boost/asio.hpp>
45
46namespace neolib
47{
48 typedef boost::asio::ip::tcp tcp_protocol;
49 typedef boost::asio::ip::udp udp_protocol;
50
52 {
53 IPv4 = 0x01,
54 IPv6 = 0x02,
56 };
57
58 template <typename Protocol>
59 inline protocol_family to_protocol_family(Protocol aProtocol)
60 {
61 if (aProtocol == aProtocol.v4())
62 return IPv4;
63 else
64 return IPv6;
65 }
66
67 template <typename Protocol>
68 inline Protocol to_protocol(protocol_family aProtocolFamily)
69 {
70 if (aProtocolFamily & IPv4)
71 return Protocol::v4();
72 else
73 return Protocol::v6();
74 }
75
76 template <typename Protocol>
78 {
79 // types
80 public:
82 typedef Protocol protocol_type;
83 private:
84 typedef typename protocol_type::endpoint endpoint_type;
85 typedef typename protocol_type::resolver resolver_type;
86 public:
87 typedef typename resolver_type::iterator iterator;
88 public:
90 {
91 public:
92 virtual void host_resolved(const std::string& aHostName, iterator aHost) = 0;
93 virtual void host_not_resolved(const std::string& aHostName, const boost::system::error_code& aError) = 0;
94 };
95 class request
96 {
97 public:
98 struct no_requester : std::logic_error { no_requester() : std::logic_error("neolib::basic_resolver::request::no_requester") {} };
99 private:
101 public:
102 request(basic_resolver<Protocol>& aParent, requester_type& aRequester, const std::string& aHostName, neolib::protocol_family aProtocolFamily) :
103 iParent(aParent), iOrphaned(false), iRequester(&aRequester), iHostName(aHostName), iProtocolFamily(aProtocolFamily)
104 {
105 }
106 public:
107 void orphan()
108 {
109 iOrphaned = true;
110 }
111 const std::string& host_name() const
112 {
113 return iHostName;
114 }
116 {
117 return iProtocolFamily;
118 }
119 bool has_requester() const
120 {
121 return iRequester != nullptr;
122 }
124 {
125 if (iRequester == nullptr)
126 throw no_requester();
127 return *iRequester;
128 }
129 void reset()
130 {
131 iRequester = nullptr;
132 }
133 void handle_resolve(const boost::system::error_code& aError, iterator aEndPointIterator)
134 {
135 if (!iOrphaned)
136 iParent.handle_resolve(*this, aError, aEndPointIterator);
137 }
138 private:
140 bool iOrphaned;
141 requester_type* iRequester;
142 std::string iHostName;
143 neolib::protocol_family iProtocolFamily;
144 };
145 typedef std::shared_ptr<request> request_pointer;
146 typedef std::vector<request_pointer> request_list;
147
148 // exceptions
149 public:
150
151 // construction
152 public:
154 iIoTask(aIoTask),
155 iResolver(aIoTask.io_service().native_object())
156 {
157 }
159 {
160 for (auto& r : iRequests)
161 r->orphan();
162 iRequests.clear();
163 iResolver.cancel();
164 }
165
166 // operations
167 public:
168 void resolve(requester& aRequester, const std::string& aHostName, protocol_family aProtocolFamily = IPv4orIPv6)
169 {
170 request_pointer newRequest(new request(*this, aRequester, aHostName, aProtocolFamily));
171 iRequests.push_back(newRequest);
172 iResolver.async_resolve(typename resolver_type::query{ aHostName, "0" },
173 boost::bind(&request::handle_resolve, *newRequest, boost::asio::placeholders::error, boost::asio::placeholders::iterator));
174 }
175 void remove_requester(requester& aRequester)
176 {
177 for (auto& request : iRequests)
178 if (request.has_requester() && request.requester() == &aRequester)
179 request.reset();
180 }
181
182 // implementation
183 private:
184 void handle_resolve(request& aRequest, const boost::system::error_code& aError, iterator aEndPointIterator)
185 {
186 if (aRequest.has_requester())
187 {
188 if (!aError)
189 {
190 bool foundGoodMatch = false;
191 for (iterator i = aEndPointIterator; !foundGoodMatch && i != iterator(); ++i)
192 {
193 endpoint_type endpoint = *i;
194 if (to_protocol_family(endpoint.protocol()) & aRequest.protocol_family())
195 {
196 foundGoodMatch = true;
197 aRequest.requester().host_resolved(aRequest.host_name(), i);
198 }
199 }
200 if (!foundGoodMatch)
201 aRequest.requester().host_resolved(aRequest.host_name(), aEndPointIterator);
202 }
203 else
204 aRequest.requester().host_not_resolved(aRequest.host_name(), aError);
205 }
206 for (auto i = iRequests.begin(); i != iRequests.end(); ++i)
207 if (&**i == &aRequest)
208 {
209 iRequests.erase(i);
210 break;
211 }
212 }
213
214 // attibutes
215 private:
216 async_task& iIoTask;
217 resolver_type iResolver;
218 request_list iRequests;
219 };
220
223}
request(basic_resolver< Protocol > &aParent, requester_type &aRequester, const std::string &aHostName, neolib::protocol_family aProtocolFamily)
Definition resolver.hpp:102
void handle_resolve(const boost::system::error_code &aError, iterator aEndPointIterator)
Definition resolver.hpp:133
requester_type & requester() const
Definition resolver.hpp:123
const std::string & host_name() const
Definition resolver.hpp:111
neolib::protocol_family protocol_family() const
Definition resolver.hpp:115
virtual void host_not_resolved(const std::string &aHostName, const boost::system::error_code &aError)=0
virtual void host_resolved(const std::string &aHostName, iterator aHost)=0
std::vector< request_pointer > request_list
Definition resolver.hpp:146
resolver_type::iterator iterator
Definition resolver.hpp:87
void resolve(requester &aRequester, const std::string &aHostName, protocol_family aProtocolFamily=IPv4orIPv6)
Definition resolver.hpp:168
basic_resolver< Protocol > our_type
Definition resolver.hpp:81
std::shared_ptr< request > request_pointer
Definition resolver.hpp:145
basic_resolver(async_task &aIoTask)
Definition resolver.hpp:153
void remove_requester(requester &aRequester)
Definition resolver.hpp:175
basic_resolver< tcp_protocol > tcp_resolver
Definition resolver.hpp:221
boost::asio::ip::tcp tcp_protocol
protocol_family to_protocol_family(Protocol aProtocol)
Definition resolver.hpp:59
boost::asio::ip::udp udp_protocol
Protocol to_protocol(protocol_family aProtocolFamily)
Definition resolver.hpp:68
basic_resolver< udp_protocol > udp_resolver
Definition resolver.hpp:222
protocol_family
Definition resolver.hpp:52
@ IPv4orIPv6
Definition resolver.hpp:55