blob: 7c992ff328ddac2f6e09af31e643f9edce9c3961 [file] [log] [blame]
Vince Lehman7a6bb352014-09-22 15:58:19 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev5946ed12015-01-19 23:41:39 -08003 * Copyright (c) 2013-2015 Regents of the University of California.
Vince Lehman7a6bb352014-09-22 15:58:19 -05004 *
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 {
Alexander Afanasyev1286e022015-01-26 10:42:29 -080052 BoostResolver::query query(host, NULL_PORT);
Vince Lehman7a6bb352014-09-22 15:58:19 -050053
54 m_resolver.async_resolve(query, bind(&Resolver::onResolveSuccess, this, _1, _2, self));
55
56 m_resolveTimeout = m_scheduler.scheduleEvent(timeout,
57 bind(&Resolver::onResolveError, this,
58 "Timeout", self));
59 }
60
61 BoostResolver::iterator
62 syncResolve(BoostResolver::query query)
63 {
64 return m_resolver.resolve(query);
65 }
66
67 void
68 onResolveSuccess(const boost::system::error_code& error,
69 BoostResolver::iterator remoteEndpoint,
70 const shared_ptr<Resolver>& self)
71 {
72 m_scheduler.cancelEvent(m_resolveTimeout);
73
74 if (error)
75 {
76 if (error == boost::system::errc::operation_canceled)
77 {
78 return;
79 }
80
81 return m_onError("Remote endpoint hostname or port cannot be resolved: " +
82 error.category().message(error.value()));
83 }
84
85 BoostResolver::iterator end;
86 for (; remoteEndpoint != end; ++remoteEndpoint)
87 {
88 IpAddress address(EndPoint(*remoteEndpoint).address());
89
90 if (m_addressSelector(address))
91 {
92 return m_onSuccess(address);
93 }
94 }
95
96 m_onError("No endpoint matching the specified address selector found");
97 }
98
99 void
100 onResolveError(const std::string& errorInfo, const shared_ptr<Resolver>& self)
101 {
102 m_resolver.cancel();
103 m_onError(errorInfo);
104 }
105
106public:
107 static const std::string NULL_PORT;
108
109private:
110 BoostResolver m_resolver;
111 EventId m_resolveTimeout;
112
113 ndn::dns::AddressSelector m_addressSelector;
114 SuccessCallback m_onSuccess;
115 ErrorCallback m_onError;
116
117 Scheduler m_scheduler;
118};
119
120const std::string Resolver::NULL_PORT = "";
121
122void
123asyncResolve(const std::string& host,
124 const SuccessCallback& onSuccess,
125 const ErrorCallback& onError,
126 boost::asio::io_service& ioService,
127 const ndn::dns::AddressSelector& addressSelector,
128 const time::nanoseconds& timeout)
129{
130 shared_ptr<Resolver> resolver = make_shared<Resolver>(onSuccess, onError,
131 addressSelector, ndn::ref(ioService));
132 resolver->asyncResolve(host, timeout, resolver);
133 // resolver will be destroyed when async operation finishes or global IO service stops
134}
135
136IpAddress
137syncResolve(const std::string& host, boost::asio::io_service& ioService,
138 const ndn::dns::AddressSelector& addressSelector)
139{
140 Resolver resolver(SuccessCallback(), ErrorCallback(), addressSelector, ioService);
141
Alexander Afanasyev1286e022015-01-26 10:42:29 -0800142 BoostResolver::query query(host, Resolver::NULL_PORT);
Vince Lehman7a6bb352014-09-22 15:58:19 -0500143
144 BoostResolver::iterator remoteEndpoint = resolver.syncResolve(query);
145
146 BoostResolver::iterator end;
147 for (; remoteEndpoint != end; ++remoteEndpoint)
148 {
149 if (addressSelector(EndPoint(*remoteEndpoint).address()))
150 {
151 return EndPoint(*remoteEndpoint).address();
152 }
153 }
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700154 BOOST_THROW_EXCEPTION(Error("No endpoint matching the specified address selector found"));
Vince Lehman7a6bb352014-09-22 15:58:19 -0500155}
156
157} // namespace dns
158} // namespace ndn