blob: 8df097f5cec40ea85c7f8442c9ec66000a0869bc [file] [log] [blame]
Vince Lehman7a6bb352014-09-22 15:58:19 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2013-2014 Regents of the University of California.
4 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
22#include "dns.hpp"
23
24#include "scheduler.hpp"
25
26namespace ndn {
27namespace dns {
28
29typedef boost::asio::ip::udp::endpoint EndPoint;
30typedef boost::asio::ip::basic_resolver<boost::asio::ip::udp> BoostResolver;
31
32class Resolver : noncopyable
33{
34public:
35 Resolver(const SuccessCallback& onSuccess,
36 const ErrorCallback& onError,
37 const ndn::dns::AddressSelector& addressSelector,
38 boost::asio::io_service& ioService)
39 : m_resolver(ioService)
40 , m_addressSelector(addressSelector)
41 , m_onSuccess(onSuccess)
42 , m_onError(onError)
43 , m_scheduler(ioService)
44 {
45 }
46
47 void
48 asyncResolve(const std::string& host,
49 const time::nanoseconds& timeout,
50 const shared_ptr<Resolver>& self)
51 {
52 BoostResolver::query query(host, NULL_PORT
53
54#if not defined(__FreeBSD__)
55 , BoostResolver::query::all_matching
56#endif
57 );
58
59 m_resolver.async_resolve(query, bind(&Resolver::onResolveSuccess, this, _1, _2, self));
60
61 m_resolveTimeout = m_scheduler.scheduleEvent(timeout,
62 bind(&Resolver::onResolveError, this,
63 "Timeout", self));
64 }
65
66 BoostResolver::iterator
67 syncResolve(BoostResolver::query query)
68 {
69 return m_resolver.resolve(query);
70 }
71
72 void
73 onResolveSuccess(const boost::system::error_code& error,
74 BoostResolver::iterator remoteEndpoint,
75 const shared_ptr<Resolver>& self)
76 {
77 m_scheduler.cancelEvent(m_resolveTimeout);
78
79 if (error)
80 {
81 if (error == boost::system::errc::operation_canceled)
82 {
83 return;
84 }
85
86 return m_onError("Remote endpoint hostname or port cannot be resolved: " +
87 error.category().message(error.value()));
88 }
89
90 BoostResolver::iterator end;
91 for (; remoteEndpoint != end; ++remoteEndpoint)
92 {
93 IpAddress address(EndPoint(*remoteEndpoint).address());
94
95 if (m_addressSelector(address))
96 {
97 return m_onSuccess(address);
98 }
99 }
100
101 m_onError("No endpoint matching the specified address selector found");
102 }
103
104 void
105 onResolveError(const std::string& errorInfo, const shared_ptr<Resolver>& self)
106 {
107 m_resolver.cancel();
108 m_onError(errorInfo);
109 }
110
111public:
112 static const std::string NULL_PORT;
113
114private:
115 BoostResolver m_resolver;
116 EventId m_resolveTimeout;
117
118 ndn::dns::AddressSelector m_addressSelector;
119 SuccessCallback m_onSuccess;
120 ErrorCallback m_onError;
121
122 Scheduler m_scheduler;
123};
124
125const std::string Resolver::NULL_PORT = "";
126
127void
128asyncResolve(const std::string& host,
129 const SuccessCallback& onSuccess,
130 const ErrorCallback& onError,
131 boost::asio::io_service& ioService,
132 const ndn::dns::AddressSelector& addressSelector,
133 const time::nanoseconds& timeout)
134{
135 shared_ptr<Resolver> resolver = make_shared<Resolver>(onSuccess, onError,
136 addressSelector, ndn::ref(ioService));
137 resolver->asyncResolve(host, timeout, resolver);
138 // resolver will be destroyed when async operation finishes or global IO service stops
139}
140
141IpAddress
142syncResolve(const std::string& host, boost::asio::io_service& ioService,
143 const ndn::dns::AddressSelector& addressSelector)
144{
145 Resolver resolver(SuccessCallback(), ErrorCallback(), addressSelector, ioService);
146
147 BoostResolver::query query(host, Resolver::NULL_PORT
148#if not defined(__FreeBSD__)
149 , BoostResolver::query::all_matching
150#endif
151 );
152
153 BoostResolver::iterator remoteEndpoint = resolver.syncResolve(query);
154
155 BoostResolver::iterator end;
156 for (; remoteEndpoint != end; ++remoteEndpoint)
157 {
158 if (addressSelector(EndPoint(*remoteEndpoint).address()))
159 {
160 return EndPoint(*remoteEndpoint).address();
161 }
162 }
163 throw Error("No endpoint matching the specified address selector found");
164}
165
166} // namespace dns
167} // namespace ndn