tools/ndn-autoconfig/main.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "core/version.hpp"
27 
28 #include "multicast-discovery.hpp"
31 
32 #include <ndn-cxx/util/network-monitor.hpp>
33 #include <ndn-cxx/util/scheduler.hpp>
34 #include <ndn-cxx/util/scheduler-scoped-event-id.hpp>
35 
36 #include <boost/noncopyable.hpp>
37 #include <boost/program_options/options_description.hpp>
38 #include <boost/program_options/variables_map.hpp>
39 #include <boost/program_options/parsers.hpp>
40 
41 namespace po = boost::program_options;
42 
43 namespace ndn {
44 namespace tools {
45 
46 class NdnAutoconfig : boost::noncopyable
47 {
48 public:
49  class Error : public std::runtime_error
50  {
51  public:
52  explicit
53  Error(const std::string& what)
54  : std::runtime_error(what)
55  {
56  }
57  };
58 
59  explicit
60  NdnAutoconfig(bool isDaemonMode)
61  : m_face(m_io)
62  , m_scheduler(m_io)
63  , m_startStagesEvent(m_scheduler)
64  , m_isDaemonMode(isDaemonMode)
65  , m_terminationSignalSet(m_io)
66  , m_stage1(m_face, m_keyChain,
67  [&] (const std::string& errorMessage) {
68  std::cerr << "Stage 1 failed: " << errorMessage << std::endl;
69  m_stage2.start();
70  })
71  , m_stage2(m_face, m_keyChain,
72  [&] (const std::string& errorMessage) {
73  std::cerr << "Stage 2 failed: " << errorMessage << std::endl;
74  m_stage3.start();
75  })
76  , m_stage3(m_face, m_keyChain,
77  [&] (const std::string& errorMessage) {
78  std::cerr << "Stage 3 failed: " << errorMessage << std::endl;
79  if (!m_isDaemonMode)
80  BOOST_THROW_EXCEPTION(Error("No more stages, automatic discovery failed"));
81  else
82  std::cerr << "No more stages, automatic discovery failed" << std::endl;
83  })
84  {
85  if (m_isDaemonMode) {
86  m_networkMonitor.reset(new util::NetworkMonitor(m_io));
87  m_networkMonitor->onNetworkStateChanged.connect([this] {
88  // delay stages, so if multiple events are triggered in short sequence,
89  // only one auto-detection procedure is triggered
90  m_startStagesEvent = m_scheduler.scheduleEvent(time::seconds(5),
91  bind(&NdnAutoconfig::startStages, this));
92  });
93  }
94 
95  // Delay a little bit
96  m_startStagesEvent = m_scheduler.scheduleEvent(time::milliseconds(100),
97  bind(&NdnAutoconfig::startStages, this));
98  }
99 
100  void
101  run()
102  {
103  if (m_isDaemonMode) {
104  m_terminationSignalSet.add(SIGINT);
105  m_terminationSignalSet.add(SIGTERM);
106  m_terminationSignalSet.async_wait(bind(&NdnAutoconfig::terminate, this, _1, _2));
107  }
108 
109  m_io.run();
110  }
111 
112  void
113  terminate(const boost::system::error_code& error, int signalNo)
114  {
115  if (error)
116  return;
117 
118  m_io.stop();
119  }
120 
121 
122  static void
123  usage(std::ostream& os,
124  const po::options_description& optionDescription,
125  const char* programName)
126  {
127  os << "Usage:\n"
128  << " " << programName << " [options]\n"
129  << "\n";
130  os << optionDescription;
131  }
132 
133 private:
134  void
135  startStages()
136  {
137  m_stage1.start();
138  if (m_isDaemonMode) {
139  m_startStagesEvent = m_scheduler.scheduleEvent(time::hours(1),
140  bind(&NdnAutoconfig::startStages, this));
141  }
142  }
143 
144 private:
145  boost::asio::io_service m_io;
146  Face m_face;
147  KeyChain m_keyChain;
148  unique_ptr<util::NetworkMonitor> m_networkMonitor;
149  util::Scheduler m_scheduler;
150  util::scheduler::ScopedEventId m_startStagesEvent;
151  bool m_isDaemonMode;
152  boost::asio::signal_set m_terminationSignalSet;
153 
154  autoconfig::MulticastDiscovery m_stage1;
155  autoconfig::GuessFromSearchDomains m_stage2;
156  autoconfig::GuessFromIdentityName m_stage3;
157 };
158 
159 } // namespace tools
160 } // namespace ndn
161 
162 int
163 main(int argc, char** argv)
164 {
165  bool isDaemonMode = false;
166  std::string configFile;
167 
168  po::options_description optionDescription("Options");
169  optionDescription.add_options()
170  ("help,h", "produce help message")
171  ("daemon,d", po::bool_switch(&isDaemonMode)->default_value(isDaemonMode),
172  "run in daemon mode, detecting network change events and re-running "
173  "auto-discovery procedure. In addition, the auto-discovery procedure "
174  "is unconditionally re-run every hour.\n"
175  "NOTE: if connection to NFD fails, the daemon will be terminated.")
176  ("config,c", po::value<std::string>(&configFile), "configuration file. If `enabled = true` "
177  "is not specified, no actions will be performed.")
178  ("version,V", "show version and exit")
179  ;
180 
181  po::variables_map options;
182  try {
183  po::store(po::parse_command_line(argc, argv, optionDescription), options);
184  po::notify(options);
185  }
186  catch (const std::exception& e) {
187  std::cerr << "ERROR: " << e.what() << "\n" << std::endl;
188  ndn::tools::NdnAutoconfig::usage(std::cerr, optionDescription, argv[0]);
189  return 1;
190  }
191 
192  if (options.count("help")) {
193  ndn::tools::NdnAutoconfig::usage(std::cout, optionDescription, argv[0]);
194  return 0;
195  }
196 
197  if (options.count("version")) {
198  std::cout << NFD_VERSION_BUILD_STRING << std::endl;
199  return 0;
200  }
201 
202  // Enable (one-shot or daemon mode whenever config file is not specified)
203  bool isEnabled = true;
204 
205  po::options_description configFileOptions;
206  configFileOptions.add_options()
207  ("enabled", po::value<bool>(&isEnabled))
208  ;
209 
210  if (!configFile.empty()) {
211  isEnabled = false; // Disable by default if config file is specified
212  try {
213  po::store(po::parse_config_file<char>(configFile.c_str(), configFileOptions), options);
214  po::notify(options);
215  }
216  catch (const std::exception& e) {
217  std::cerr << "ERROR: " << e.what() << std::endl << std::endl;
218  return 1;
219  }
220  }
221 
222  if (!isEnabled) {
223  return 0;
224  }
225 
226  try {
227  ndn::tools::NdnAutoconfig autoConfigInstance(isDaemonMode);
228  autoConfigInstance.run();
229  }
230  catch (const std::exception& error) {
231  std::cerr << "ERROR: " << error.what() << std::endl;
232  return 1;
233  }
234  return 0;
235 }
Copyright (c) 2014-2016, Regents of the University of California, Arizona Board of Regents...
Definition: nfd.hpp:35
static void usage(const char *programName)
STL namespace.
int main(int argc, char **argv)