main.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014-2017, Regents of the University of California,
4  * Arizona Board of Regents,
5  * Colorado State University,
6  * University Pierre & Marie Curie, Sorbonne University,
7  * Washington University in St. Louis,
8  * Beijing Institute of Technology,
9  * The University of Memphis.
10  *
11  * This file is part of NFD (Named Data Networking Forwarding Daemon).
12  * See AUTHORS.md for complete list of NFD authors and contributors.
13  *
14  * NFD is free software: you can redistribute it and/or modify it under the terms
15  * of the GNU General Public License as published by the Free Software Foundation,
16  * either version 3 of the License, or (at your option) any later version.
17  *
18  * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20  * PURPOSE. See the GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License along with
23  * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24  */
25 
26 #include "procedure.hpp"
28 #include "core/scheduler.hpp"
29 #include "core/version.hpp"
30 
31 #include <signal.h>
32 #include <string.h>
33 #include <boost/program_options/options_description.hpp>
34 #include <boost/program_options/parsers.hpp>
35 #include <boost/program_options/variables_map.hpp>
36 #include <ndn-cxx/net/network-monitor.hpp>
37 #include <ndn-cxx/util/scheduler.hpp>
38 #include <ndn-cxx/util/scheduler-scoped-event-id.hpp>
39 #include <ndn-cxx/util/time.hpp>
40 
41 // suppress warning caused by boost::program_options::parse_config_file
42 #ifdef __clang__
43 #pragma clang diagnostic ignored "-Wundefined-func-template"
44 #endif
45 
46 namespace ndn {
47 namespace tools {
48 namespace autoconfig {
49 // ndn-autoconfig is an NDN tool not an NFD tool, so it uses ndn::tools::autoconfig namespace.
50 // It lives in NFD repository because nfd-start can automatically start ndn-autoconfig in daemon mode.
51 
52 static const time::nanoseconds DAEMON_INITIAL_DELAY = time::milliseconds(100);
53 static const time::nanoseconds DAEMON_UNCONDITIONAL_INTERVAL = time::hours(1);
54 static const time::nanoseconds NETMON_DAMPEN_PERIOD = time::seconds(5);
55 
56 namespace po = boost::program_options;
57 
58 static void
59 usage(std::ostream& os,
60  const po::options_description& optionsDescription,
61  const char* programName)
62 {
63  os << "Usage:\n"
64  << " " << programName << " [options]\n"
65  << "\n";
66  os << optionsDescription;
67 }
68 
69 static void
71 {
72  boost::asio::signal_set terminateSignals(proc.getIoService());
73  terminateSignals.add(SIGINT);
74  terminateSignals.add(SIGTERM);
75  terminateSignals.async_wait([&] (const boost::system::error_code& error, int signalNo) {
76  if (error) {
77  return;
78  }
79  const char* signalName = ::strsignal(signalNo);
80  std::cerr << "Exit on signal ";
81  if (signalName == nullptr) {
82  std::cerr << signalNo;
83  }
84  else {
85  std::cerr << signalName;
86  }
87  std::cerr << std::endl;
88  proc.getIoService().stop();
89  });
90 
91  util::Scheduler sched(proc.getIoService());
92  util::scheduler::ScopedEventId runEvt(sched);
93  auto scheduleRerun = [&] (time::nanoseconds delay) {
94  runEvt = sched.scheduleEvent(delay, [&] { proc.runOnce(); });
95  };
96 
97  proc.onComplete.connect([&] (bool isSuccess) {
98  scheduleRerun(DAEMON_UNCONDITIONAL_INTERVAL);
99  });
100 
101  net::NetworkMonitor netmon(proc.getIoService());
102  netmon.onNetworkStateChanged.connect([&] { scheduleRerun(NETMON_DAMPEN_PERIOD); });
103 
104  scheduleRerun(DAEMON_INITIAL_DELAY);
105  proc.getIoService().run();
106 }
107 
108 static int
109 main(int argc, char** argv)
110 {
111  Options options;
112  bool isDaemon = false;
113  std::string configFile;
114 
115  po::options_description optionsDescription("Options");
116  optionsDescription.add_options()
117  ("help,h", "print this message and exit")
118  ("version,V", "display version and exit")
119  ("daemon,d", po::bool_switch(&isDaemon)->default_value(isDaemon),
120  "run in daemon mode, detecting network change events and re-running auto-discovery procedure. "
121  "In addition, the auto-discovery procedure is unconditionally re-run every hour.\n"
122  "NOTE: if connection to NFD fails, the daemon will be terminated.")
123  ("ndn-fch-url", po::value<std::string>(&options.ndnFchUrl)->default_value(options.ndnFchUrl),
124  "URL for NDN-FCH (Find Closest Hub) service")
125  ("config,c", po::value<std::string>(&configFile),
126  "configuration file. Exit immediately if `enabled = true` is not specified in config file.")
127  ;
128 
129  po::variables_map vm;
130  try {
131  po::store(po::parse_command_line(argc, argv, optionsDescription), vm);
132  po::notify(vm);
133  }
134  catch (const std::exception& e) {
135  std::cerr << "ERROR: " << e.what() << "\n" << "\n\n";
136  usage(std::cerr, optionsDescription, argv[0]);
137  return 2;
138  }
139 
140  if (vm.count("help")) {
141  usage(std::cout, optionsDescription, argv[0]);
142  return 0;
143  }
144 
145  if (vm.count("version")) {
146  std::cout << NFD_VERSION_BUILD_STRING << std::endl;
147  return 0;
148  }
149 
150  if (vm.count("config")) {
151  po::options_description configFileOptions;
152  configFileOptions.add_options()
153  ("enabled", po::value<bool>()->default_value(false))
154  ;
155  try {
156  po::store(po::parse_config_file<char>(configFile.data(), configFileOptions), vm);
157  po::notify(vm);
158  }
159  catch (const std::exception& e) {
160  std::cerr << "ERROR in config: " << e.what() << "\n\n";
161  return 2;
162  }
163  if (!vm["enabled"].as<bool>()) {
164  // not enabled in config
165  return 0;
166  }
167  }
168 
169  int exitCode = 0;
170  try {
171  Face face;
172  KeyChain keyChain;
173  Procedure proc(face, keyChain);
174  proc.initialize(options);
175 
176  if (isDaemon) {
177  runDaemon(proc);
178  }
179  else {
180  proc.onComplete.connect([&exitCode] (bool isSuccess) { exitCode = isSuccess ? 0 : 3; });
181  proc.runOnce();
182  face.processEvents();
183  }
184  }
185  catch (const std::exception& e) {
186  std::cerr << ::nfd::getExtendedErrorMessage(e) << std::endl;
187  return 1;
188  }
189  return exitCode;
190 }
191 
192 } // namespace autoconfig
193 } // namespace tools
194 } // namespace ndn
195 
196 int
197 main(int argc, char** argv)
198 {
199  return ndn::tools::autoconfig::main(argc, argv);
200 }
static const time::nanoseconds DAEMON_UNCONDITIONAL_INTERVAL
Definition: main.cpp:53
Copyright (c) 2014-2017, Regents of the University of California, Arizona Board of Regents...
static int main(int argc, char **argv)
Definition: main.cpp:109
std::string getExtendedErrorMessage(const E &exception)
std::string ndnFchUrl
HTTP base URL of NDN-FCH service.
Definition: procedure.hpp:40
void initialize(const Options &options)
Definition: procedure.cpp:52
util::Signal< Procedure, bool > onComplete
signal when procedure completes
Definition: procedure.hpp:80
static const time::nanoseconds DAEMON_INITIAL_DELAY
Definition: main.cpp:52
static void runDaemon(Procedure &proc)
Definition: main.cpp:70
static const time::nanoseconds NETMON_DAMPEN_PERIOD
Definition: main.cpp:54
static void usage(std::ostream &os, const po::options_description &optionsDescription, const char *programName)
Definition: main.cpp:59
void runOnce()
run HUB discovery procedure once
Definition: procedure.cpp:79
boost::asio::io_service & getIoService()
Definition: procedure.hpp:60