dns.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
22 #include "dns.hpp"
23 #include "../util/scheduler.hpp"
24 
25 #include <boost/asio/io_service.hpp>
26 #include <boost/asio/ip/udp.hpp>
27 
28 namespace ndn {
29 namespace dns {
30 
31 class Resolver : noncopyable
32 {
33 public:
34  typedef boost::asio::ip::udp protocol;
35  typedef protocol::resolver::iterator iterator;
36  typedef protocol::resolver::query query;
37 
38 public:
39  Resolver(boost::asio::io_service& ioService,
40  const AddressSelector& addressSelector)
41  : m_resolver(ioService)
42  , m_addressSelector(addressSelector)
43  , m_scheduler(ioService)
44  {
45  BOOST_ASSERT(m_addressSelector != nullptr);
46  }
47 
48  void
49  asyncResolve(const query& q,
50  const SuccessCallback& onSuccess,
51  const ErrorCallback& onError,
52  time::nanoseconds timeout,
53  const shared_ptr<Resolver>& self)
54  {
55  m_onSuccess = onSuccess;
56  m_onError = onError;
57 
58  m_resolver.async_resolve(q, bind(&Resolver::onResolveResult, this, _1, _2, self));
59 
60  m_resolveTimeout = m_scheduler.scheduleEvent(timeout, bind(&Resolver::onResolveTimeout, this, self));
61  }
62 
63  iterator
64  syncResolve(const query& q)
65  {
66  return selectAddress(m_resolver.resolve(q));
67  }
68 
69 private:
70  void
71  onResolveResult(const boost::system::error_code& error,
72  iterator it, const shared_ptr<Resolver>& self)
73  {
74  m_scheduler.cancelEvent(m_resolveTimeout);
75  // ensure the Resolver isn't destructed while callbacks are still pending, see #2653
76  m_resolver.get_io_service().post(bind([] (const shared_ptr<Resolver>&) {}, self));
77 
78  if (error) {
79  if (error == boost::asio::error::operation_aborted)
80  return;
81 
82  if (m_onError)
83  m_onError("Hostname cannot be resolved: " + error.message());
84 
85  return;
86  }
87 
88  it = selectAddress(it);
89 
90  if (it != iterator() && m_onSuccess) {
91  m_onSuccess(it->endpoint().address());
92  }
93  else if (m_onError) {
94  m_onError("No endpoints match the specified address selector");
95  }
96  }
97 
98  void
99  onResolveTimeout(const shared_ptr<Resolver>& self)
100  {
101  m_resolver.cancel();
102  // ensure the Resolver isn't destructed while callbacks are still pending, see #2653
103  m_resolver.get_io_service().post(bind([] (const shared_ptr<Resolver>&) {}, self));
104 
105  if (m_onError)
106  m_onError("Hostname resolution timed out");
107  }
108 
109  iterator
110  selectAddress(iterator it) const
111  {
112  while (it != iterator() &&
113  !m_addressSelector(it->endpoint().address())) {
114  ++it;
115  }
116 
117  return it;
118  }
119 
120 private:
121  protocol::resolver m_resolver;
122 
123  AddressSelector m_addressSelector;
124  SuccessCallback m_onSuccess;
125  ErrorCallback m_onError;
126 
127  util::scheduler::Scheduler m_scheduler;
128  util::scheduler::EventId m_resolveTimeout;
129 };
130 
131 void
132 asyncResolve(const std::string& host,
133  const SuccessCallback& onSuccess,
134  const ErrorCallback& onError,
135  boost::asio::io_service& ioService,
136  const AddressSelector& addressSelector,
137  time::nanoseconds timeout)
138 {
139  auto resolver = make_shared<Resolver>(ref(ioService), addressSelector);
140  resolver->asyncResolve(Resolver::query(host, ""), onSuccess, onError, timeout, resolver);
141  // resolver will be destroyed when async operation finishes or ioService stops
142 }
143 
144 IpAddress
145 syncResolve(const std::string& host,
146  boost::asio::io_service& ioService,
147  const AddressSelector& addressSelector)
148 {
149  Resolver resolver(ioService, addressSelector);
150  auto it = resolver.syncResolve(Resolver::query(host, ""));
151 
152  if (it == Resolver::iterator()) {
153  BOOST_THROW_EXCEPTION(Error("No endpoints match the specified address selector"));
154  }
155 
156  return it->endpoint().address();
157 }
158 
159 } // namespace dns
160 } // namespace ndn
Copyright (c) 2013-2017 Regents of the University of California.
Definition: common.hpp:66
function< void(const IpAddress &address)> SuccessCallback
Definition: dns.hpp:72
IpAddress syncResolve(const std::string &host, boost::asio::io_service &ioService, const AddressSelector &addressSelector)
Synchronously resolve host.
Definition: dns.cpp:145
function< bool(const IpAddress &address)> AddressSelector
Definition: dns.hpp:34
function< void(const std::string &reason)> ErrorCallback
Definition: dns.hpp:73
boost::asio::ip::address IpAddress
Definition: dns.hpp:33
Identifies a scheduled event.
Definition: scheduler.hpp:53
void asyncResolve(const std::string &host, const SuccessCallback &onSuccess, const ErrorCallback &onError, boost::asio::io_service &ioService, const AddressSelector &addressSelector, time::nanoseconds timeout)
Asynchronously resolve host.
Definition: dns.cpp:132