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-2023, 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"
27 #include "core/version.hpp"
28 
29 #include <signal.h>
30 #include <string.h>
31 
32 #include <boost/asio/signal_set.hpp>
33 #include <boost/exception/diagnostic_information.hpp>
34 #include <boost/program_options/options_description.hpp>
35 #include <boost/program_options/parsers.hpp>
36 #include <boost/program_options/variables_map.hpp>
37 
38 #include <ndn-cxx/net/network-monitor.hpp>
39 #include <ndn-cxx/util/scheduler.hpp>
40 #include <ndn-cxx/util/time.hpp>
41 
42 namespace ndn::autoconfig {
43 
44 namespace po = boost::program_options;
45 
46 constexpr time::nanoseconds DAEMON_INITIAL_DELAY = 100_ms;
47 constexpr time::nanoseconds DAEMON_UNCONDITIONAL_INTERVAL = 1_h;
48 constexpr time::nanoseconds NETMON_DAMPEN_PERIOD = 5_s;
49 
50 static void
51 usage(std::ostream& os,
52  const po::options_description& opts,
53  const char* programName)
54 {
55  os << "Usage: " << programName << " [options]\n"
56  << "\n"
57  << opts;
58 }
59 
60 static void
62 {
63  boost::asio::signal_set terminateSignals(proc.getIoContext());
64  terminateSignals.add(SIGINT);
65  terminateSignals.add(SIGTERM);
66  terminateSignals.async_wait([&] (const auto& error, int signalNo) {
67  if (error) {
68  return;
69  }
70  const char* signalName = ::strsignal(signalNo);
71  std::cerr << "Exiting on signal ";
72  if (signalName == nullptr) {
73  std::cerr << signalNo;
74  }
75  else {
76  std::cerr << signalName;
77  }
78  std::cerr << std::endl;
79  proc.getIoContext().stop();
80  });
81 
82  Scheduler sched(proc.getIoContext());
83  scheduler::ScopedEventId runEvt;
84  auto scheduleRerun = [&] (time::nanoseconds delay) {
85  runEvt = sched.schedule(delay, [&] { proc.runOnce(); });
86  };
87 
88  proc.onComplete.connect([&] (bool isSuccess) {
89  scheduleRerun(DAEMON_UNCONDITIONAL_INTERVAL);
90  });
91 
92  net::NetworkMonitor netmon(proc.getIoContext());
93  netmon.onNetworkStateChanged.connect([&] { scheduleRerun(NETMON_DAMPEN_PERIOD); });
94 
95  scheduleRerun(DAEMON_INITIAL_DELAY);
96  proc.getIoContext().run();
97 }
98 
99 static int
100 main(int argc, char** argv)
101 {
102  Options options;
103  bool isDaemon = false;
104  std::string configFile;
105 
106  po::options_description optionsDescription("Options");
107  optionsDescription.add_options()
108  ("help,h", "print this message and exit")
109  ("version,V", "show version information and exit")
110  ("daemon,d", po::bool_switch(&isDaemon)->default_value(isDaemon),
111  "Run in daemon mode, detecting network change events and re-running the auto-discovery procedure. "
112  "In addition, the auto-discovery procedure is unconditionally re-run every hour.\n"
113  "NOTE: if the connection to NFD fails, the daemon will exit.")
114  ("ndn-fch-url", po::value<std::string>(&options.ndnFchUrl)->default_value(options.ndnFchUrl),
115  "URL for NDN-FCH (Find Closest Hub) service")
116  ("config,c", po::value<std::string>(&configFile),
117  "Configuration file. Exit immediately unless 'enabled = true' is specified in the config file.")
118  ;
119 
120  po::variables_map vm;
121  try {
122  po::store(po::parse_command_line(argc, argv, optionsDescription), vm);
123  po::notify(vm);
124  }
125  catch (const std::exception& e) {
126  std::cerr << "ERROR: " << e.what() << "\n\n";
127  usage(std::cerr, optionsDescription, argv[0]);
128  return 2;
129  }
130 
131  if (vm.count("help")) {
132  usage(std::cout, optionsDescription, argv[0]);
133  return 0;
134  }
135 
136  if (vm.count("version")) {
137  std::cout << NFD_VERSION_BUILD_STRING << std::endl;
138  return 0;
139  }
140 
141  if (vm.count("config")) {
142  po::options_description configFileOptions;
143  configFileOptions.add_options()
144  ("enabled", po::value<bool>()->default_value(false))
145  ;
146  try {
147  po::store(po::parse_config_file<char>(configFile.data(), configFileOptions), vm);
148  po::notify(vm);
149  }
150  catch (const std::exception& e) {
151  std::cerr << "ERROR in config: " << e.what() << "\n\n";
152  return 2;
153  }
154  if (!vm["enabled"].as<bool>()) {
155  // not enabled in config
156  return 0;
157  }
158  }
159 
160  int exitCode = 0;
161  try {
162  Face face;
163  KeyChain keyChain;
164  Procedure proc(face, keyChain);
165  proc.initialize(options);
166 
167  if (isDaemon) {
168  runDaemon(proc);
169  }
170  else {
171  proc.onComplete.connect([&exitCode] (bool isSuccess) { exitCode = isSuccess ? 0 : 1; });
172  proc.runOnce();
173  face.processEvents();
174  }
175  }
176  catch (const std::exception& e) {
177  std::cerr << "ERROR: " << boost::diagnostic_information(e);
178  return 1;
179  }
180 
181  return exitCode;
182 }
183 
184 } // namespace ndn::autoconfig
185 
186 int
187 main(int argc, char** argv)
188 {
189  return ndn::autoconfig::main(argc, argv);
190 }
signal::Signal< Procedure, bool > onComplete
Signal emitted when the procedure completes.
Definition: procedure.hpp:83
void initialize(const Options &options)
Definition: procedure.cpp:50
boost::asio::io_context & getIoContext() const noexcept
Definition: procedure.hpp:62
void runOnce()
Run the HUB discovery procedure once.
Definition: procedure.cpp:77
int main(int argc, char **argv)
Definition: main.cpp:250
constexpr time::nanoseconds DAEMON_UNCONDITIONAL_INTERVAL
Definition: main.cpp:47
static void usage(std::ostream &os, const po::options_description &opts, const char *programName)
Definition: main.cpp:51
static void runDaemon(Procedure &proc)
Definition: main.cpp:61
static int main(int argc, char **argv)
Definition: main.cpp:100
constexpr time::nanoseconds DAEMON_INITIAL_DELAY
Definition: main.cpp:46
constexpr time::nanoseconds NETMON_DAMPEN_PERIOD
Definition: main.cpp:48
std::string ndnFchUrl
HTTP base URL of NDN-FCH service.
Definition: procedure.hpp:41
const char NFD_VERSION_BUILD_STRING[]
NFD version string, including git commit information if NFD is build from a specific git commit.