NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.0: NDN, CCN, CCNx, content centric networks
API Documentation
main.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "nfd.hpp"
27 #include "rib/nrd.hpp"
28 
29 #include "version.hpp"
30 #include "core/global-io.hpp"
31 #include "core/logger.hpp"
33 
34 #include <string.h>
35 
36 #include <boost/filesystem.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 // boost::thread is used instead of std::thread to guarantee proper cleanup of thread local storage,
42 // see http://www.boost.org/doc/libs/1_48_0/doc/html/thread/thread_local_storage.html
43 #include <boost/thread.hpp>
44 
45 #include <atomic>
46 #include <condition_variable>
47 
48 namespace nfd {
49 
50 NFD_LOG_INIT("NFD");
51 
61 class NfdRunner : noncopyable
62 {
63 public:
64  explicit
65  NfdRunner(const std::string& configFile)
66  : m_nfd(configFile, m_nfdKeyChain)
67  , m_configFile(configFile)
68  , m_terminationSignalSet(getGlobalIoService())
69  , m_reloadSignalSet(getGlobalIoService())
70  {
71  m_terminationSignalSet.add(SIGINT);
72  m_terminationSignalSet.add(SIGTERM);
73  m_terminationSignalSet.async_wait(bind(&NfdRunner::terminate, this, _1, _2));
74 
75  m_reloadSignalSet.add(SIGHUP);
76  m_reloadSignalSet.async_wait(bind(&NfdRunner::reload, this, _1, _2));
77  }
78 
79  static void
80  printUsage(std::ostream& os, const std::string& programName)
81  {
82  os << "Usage: \n"
83  << " " << programName << " [options]\n"
84  << "\n"
85  << "Run NFD forwarding daemon\n"
86  << "\n"
87  << "Options:\n"
88  << " [--help] - print this help message\n"
89  << " [--version] - print version and exit\n"
90  << " [--modules] - list available logging modules\n"
91  << " [--config /path/to/nfd.conf] - path to configuration file "
92  << "(default: " << DEFAULT_CONFIG_FILE << ")\n"
93  ;
94  }
95 
96  static void
97  printModules(std::ostream& os)
98  {
99  os << "Available logging modules: \n";
100 
101  for (const auto& module : LoggerFactory::getInstance().getModules()) {
102  os << module << "\n";
103  }
104  }
105 
106  void
108  {
109  m_nfd.initialize();
110  }
111 
112  int
113  run()
114  {
119  std::atomic_int retval(0);
120 
121  boost::asio::io_service* const mainIo = &getGlobalIoService();
122  boost::asio::io_service* nrdIo = nullptr;
123 
124  // Mutex and conditional variable to implement synchronization between main and RIB manager
125  // threads:
126  // - to block main thread until RIB manager thread starts and initializes nrdIo (to allow
127  // stopping it later)
128  std::mutex m;
129  std::condition_variable cv;
130 
131  std::string configFile = this->m_configFile; // c++11 lambda cannot capture member variables
132  boost::thread nrdThread([configFile, &retval, &nrdIo, mainIo, &cv, &m] {
133  {
134  std::lock_guard<std::mutex> lock(m);
135  nrdIo = &getGlobalIoService();
136  BOOST_ASSERT(nrdIo != mainIo);
137  }
138  cv.notify_all(); // notify that nrdIo has been assigned
139 
140  try {
141  ndn::KeyChain nrdKeyChain;
142  // must be created inside a separate thread
143  rib::Nrd nrd(configFile, nrdKeyChain);
144  nrd.initialize();
145  getGlobalIoService().run(); // nrdIo is not thread-safe to use here
146  }
147  catch (const std::exception& e) {
148  NFD_LOG_FATAL(e.what());
149  retval = 6;
150  mainIo->stop();
151  }
152 
153  {
154  std::lock_guard<std::mutex> lock(m);
155  nrdIo = nullptr;
156  }
157  });
158 
159  {
160  // Wait to guarantee that nrdIo is properly initialized, so it can be used to terminate
161  // RIB manager thread.
162  std::unique_lock<std::mutex> lock(m);
163  cv.wait(lock, [&nrdIo] { return nrdIo != nullptr; });
164  }
165 
166  try {
167  mainIo->run();
168  }
169  catch (const std::exception& e) {
170  NFD_LOG_FATAL(e.what());
171  retval = 4;
172  }
173  catch (const PrivilegeHelper::Error& e) {
174  NFD_LOG_FATAL(e.what());
175  retval = 5;
176  }
177 
178  {
179  // nrdIo is guaranteed to be alive at this point
180  std::lock_guard<std::mutex> lock(m);
181  if (nrdIo != nullptr) {
182  nrdIo->stop();
183  nrdIo = nullptr;
184  }
185  }
186  nrdThread.join();
187 
188  return retval;
189  }
190 
191  void
192  terminate(const boost::system::error_code& error, int signalNo)
193  {
194  if (error)
195  return;
196 
197  NFD_LOG_INFO("Caught signal '" << ::strsignal(signalNo) << "', exiting...");
198  getGlobalIoService().stop();
199  }
200 
201  void
202  reload(const boost::system::error_code& error, int signalNo)
203  {
204  if (error)
205  return;
206 
207  NFD_LOG_INFO("Caught signal '" << ::strsignal(signalNo) << "', reloading...");
208  m_nfd.reloadConfigFile();
209 
210  m_reloadSignalSet.async_wait(bind(&NfdRunner::reload, this, _1, _2));
211  }
212 
213 private:
214  ndn::KeyChain m_nfdKeyChain;
215  Nfd m_nfd;
216  std::string m_configFile;
217 
218  boost::asio::signal_set m_terminationSignalSet;
219  boost::asio::signal_set m_reloadSignalSet;
220 };
221 
222 } // namespace nfd
223 
224 int
225 main(int argc, char** argv)
226 {
227  using namespace nfd;
228 
229  namespace po = boost::program_options;
230 
231  po::options_description description;
232 
233  std::string configFile = DEFAULT_CONFIG_FILE;
234  description.add_options()
235  ("help,h", "print this help message")
236  ("version,V", "print version and exit")
237  ("modules,m", "list available logging modules")
238  ("config,c", po::value<std::string>(&configFile), "path to configuration file")
239  ;
240 
241  po::variables_map vm;
242  try {
243  po::store(po::command_line_parser(argc, argv).options(description).run(), vm);
244  po::notify(vm);
245  }
246  catch (const std::exception& e) {
247  // avoid NFD_LOG_FATAL to ensure that errors related to command-line parsing always appear on the
248  // terminal and are not littered with timestamps and other things added by the logging subsystem
249  std::cerr << "ERROR: " << e.what() << std::endl;
250  NfdRunner::printUsage(std::cerr, argv[0]);
251  return 1;
252  }
253 
254  if (vm.count("help") > 0) {
255  NfdRunner::printUsage(std::cout, argv[0]);
256  return 0;
257  }
258 
259  if (vm.count("version") > 0) {
260  std::cout << NFD_VERSION_BUILD_STRING << std::endl;
261  return 0;
262  }
263 
264  if (vm.count("modules") > 0) {
265  NfdRunner::printModules(std::cout);
266  return 0;
267  }
268 
269  NfdRunner runner(configFile);
270 
271  try {
272  runner.initialize();
273  }
274  catch (const boost::filesystem::filesystem_error& e) {
275  if (e.code() == boost::system::errc::permission_denied) {
276  NFD_LOG_FATAL("Permissions denied for " << e.path1() << ". " <<
277  argv[0] << " should be run as superuser");
278  return 3;
279  }
280  else {
281  NFD_LOG_FATAL(e.what());
282  return 2;
283  }
284  }
285  catch (const std::exception& e) {
286  NFD_LOG_FATAL(e.what());
287  return 2;
288  }
289  catch (const PrivilegeHelper::Error& e) {
290  // PrivilegeHelper::Errors do not inherit from std::exception
291  // and represent seteuid/gid failures
292 
293  NFD_LOG_FATAL(e.what());
294  return 3;
295  }
296 
297  return runner.run();
298 }
static void printUsage(std::ostream &os, const std::string &programName)
Definition: main.cpp:80
void initialize()
Definition: main.cpp:107
represents a serious seteuid/gid failure
int main(int argc, char **argv)
Definition: main.cpp:225
static void printModules(std::ostream &os)
Definition: main.cpp:97
NfdRunner(const std::string &configFile)
Definition: main.cpp:65
Class representing NRD (NFD RIB Manager) instance This class can be used to initialize all components...
Definition: nrd.hpp:45
void reload(const boost::system::error_code &error, int signalNo)
Definition: main.cpp:202
int run()
Definition: main.cpp:113
#define NFD_LOG_INFO(expression)
Definition: logger.hpp:37
void reloadConfigFile()
Reload configuration file and apply update (if any)
Definition: nfd.cpp:177
Class representing NFD instance This class can be used to initialize all components of NFD...
Definition: nfd.hpp:49
Copyright (c) 2011-2015 Regents of the University of California.
Definition: ndn-common.hpp:38
void initialize()
Perform initialization of NFD instance After initialization, NFD instance can be started by invoking ...
Definition: nfd.cpp:70
#define NFD_LOG_INIT(name)
Definition: logger.hpp:33
Executes NFD with RIB manager.
Definition: main.cpp:61
void initialize()
Perform initialization of NFD instance After initialization, NFD instance can be started by invoking ...
Definition: nrd.cpp:63
boost::asio::io_service & getGlobalIoService()
Definition: global-io.hpp:35
#define NFD_LOG_FATAL(expression)
Definition: logger.hpp:40
#define DEFAULT_CONFIG_FILE
Definition: config.hpp:18
const char * what() const
void terminate(const boost::system::error_code &error, int signalNo)
Definition: main.cpp:192