main: Enabling system signal handling and small reorganization
Change-Id: I568c5b57e787d44b9d6a758fd7e8cdf22222234e
Refs: 1380
diff --git a/daemon/main.cpp b/daemon/main.cpp
index 44880b2..0f73167 100644
--- a/daemon/main.cpp
+++ b/daemon/main.cpp
@@ -22,141 +22,169 @@
struct ProgramOptions
{
- bool m_showUsage;
- std::string m_config;
+ bool showUsage;
+ std::string config;
};
-static ProgramOptions g_options;
-static Forwarder* g_forwarder;
-static FibManager* g_fibManager;
-static FaceManager* g_faceManager;
-static StrategyChoiceManager* g_strategyChoiceManager;
-static StatusServer* g_statusServer;
-static shared_ptr<InternalFace> g_internalFace;
-
-
-void
-usage(char* programName)
+class Nfd : noncopyable
{
- printf(
- "%s --help\n\tshow this help and exit\n"
- "%s "
- "[--config /path/to/nfd.conf]\n"
- "\trun forwarding daemon\n"
- "\t--config <configuration file>]: path to configuration file\n"
- "\n",
- programName, programName
- );
-}
+public:
+ explicit
+ Nfd(const std::string& configFile)
+ : m_internalFace(new InternalFace())
+ , m_fibManager(m_forwarder.getFib(),
+ bind(&Forwarder::getFace, &m_forwarder, _1),
+ m_internalFace)
+ , m_faceManager(m_forwarder.getFaceTable(), m_internalFace)
+ , m_strategyChoiceManager(m_forwarder.getStrategyChoice(), m_internalFace)
+ , m_statusServer(m_internalFace, m_forwarder)
+ {
+ ConfigFile config;
+ m_internalFace->getValidator().setConfigFile(config);
-bool
-parseCommandLine(int argc, char** argv)
-{
- g_options.m_showUsage = false;
- g_options.m_config = DEFAULT_CONFIG_FILE;
+ m_forwarder.addFace(m_internalFace);
- while (true) {
- int option_index = 0;
- static ::option long_options[] = {
- { "help" , no_argument , 0, 0 },
- { "config" , required_argument, 0, 0 },
- { 0 , 0 , 0, 0 }
- };
- int c = getopt_long_only(argc, argv, "", long_options, &option_index);
- if (c == -1) break;
+ m_faceManager.setConfigFile(config);
- switch (c) {
+ // parse config file
+ config.parse(configFile, true);
+ config.parse(configFile, false);
+
+ // add FIB entry for NFD Management Protocol
+ shared_ptr<fib::Entry> entry = m_forwarder.getFib().insert("/localhost/nfd").first;
+ entry->addNextHop(m_internalFace, 0);
+ }
+
+
+ static void
+ printUsage(std::ostream& os, const std::string& programName)
+ {
+ os << "Usage: \n"
+ << " " << programName << " [options]\n"
+ << "\n"
+ << "Run NFD forwarding daemon\n"
+ << "\n"
+ << "Options:\n"
+ << " [--help] - print this help message\n"
+ << " [--config /path/to/nfd.conf] - path to configuration file "
+ << "(default: " << DEFAULT_CONFIG_FILE << ")\n"
+ ;
+ }
+
+ static bool
+ parseCommandLine(int argc, char** argv, ProgramOptions& options)
+ {
+ options.showUsage = false;
+ options.config = DEFAULT_CONFIG_FILE;
+
+ while (true) {
+ int optionIndex = 0;
+ static ::option longOptions[] = {
+ { "help" , no_argument , 0, 0 },
+ { "config" , required_argument, 0, 0 },
+ { 0 , 0 , 0, 0 }
+ };
+ int c = getopt_long_only(argc, argv, "", longOptions, &optionIndex);
+ if (c == -1)
+ break;
+
+ switch (c) {
case 0:
- switch (option_index) {
- case 0://help
- g_options.m_showUsage = true;
- break;
- case 1://config
- g_options.m_config = ::optarg;
- break;
+ switch (optionIndex) {
+ case 0: // help
+ options.showUsage = true;
+ break;
+ case 1: // config
+ options.config = ::optarg;
+ break;
+ default:
+ return false;
}
break;
+ }
}
+
+ return true;
}
- return true;
-}
+ void
+ terminate(const boost::system::error_code& error,
+ int signalNo,
+ boost::asio::signal_set& signalSet)
+ {
+ if (error)
+ return;
-void
-initializeMgmt()
-{
- ConfigFile config;
-
- g_internalFace = make_shared<InternalFace>();
- g_internalFace->getValidator().setConfigFile(config);
- g_forwarder->addFace(g_internalFace);
-
- g_fibManager = new FibManager(g_forwarder->getFib(),
- bind(&Forwarder::getFace, g_forwarder, _1),
- g_internalFace);
-
- g_faceManager = new FaceManager(g_forwarder->getFaceTable(), g_internalFace);
- g_faceManager->setConfigFile(config);
-
- g_strategyChoiceManager = new StrategyChoiceManager(g_forwarder->getStrategyChoice(),
- g_internalFace);
-
- g_statusServer = new StatusServer(g_internalFace, *g_forwarder);
-
- config.parse(g_options.m_config, true);
- config.parse(g_options.m_config, false);
-
- shared_ptr<fib::Entry> entry = g_forwarder->getFib().insert("/localhost/nfd").first;
- entry->addNextHop(g_internalFace, 0);
-}
-
-int
-main(int argc, char** argv)
-{
- bool isCommandLineValid = parseCommandLine(argc, argv);
- if (!isCommandLineValid) {
- usage(argv[0]);
- return 1;
- }
- if (g_options.m_showUsage) {
- usage(argv[0]);
- return 0;
+ if (signalNo == SIGINT ||
+ signalNo == SIGTERM)
+ {
+ getGlobalIoService().stop();
+ std::cout << "Caught signal '" << strsignal(signalNo) << "', exiting..." << std::endl;
+ }
+ else
+ {
+ /// \todo May be try to reload config file (at least security section)
+ signalSet.async_wait(bind(&Nfd::terminate, this, _1, _2,
+ boost::ref(signalSet)));
+ }
}
- try {
- g_forwarder = new Forwarder();
- initializeMgmt();
+private:
+ Forwarder m_forwarder;
+ shared_ptr<InternalFace> m_internalFace;
- /// \todo Add signal processing to gracefully terminate the app
-
- getGlobalIoService().run();
- // } catch(ConfigFile::Error& error) {
- // NFD_LOG_ERROR("Error: " << error.what());
- // NFD_LOG_ERROR("You should either specify --config option or copy sample configuration into "
- // << DEFAULT_CONFIG_FILE);
- }
- catch (boost::filesystem::filesystem_error& e) {
- if (e.code() == boost::system::errc::permission_denied) {
- NFD_LOG_ERROR("Error: Permissions denied for " << e.path1());
- NFD_LOG_ERROR(argv[0] << " should be run as superuser");
- }
- else {
- NFD_LOG_ERROR("Error: " << e.what());
- }
- }
- catch (std::exception& e) {
- NFD_LOG_ERROR("Error: " << e.what());
- return 1;
- }
-
- return 0;
-}
+ FibManager m_fibManager;
+ FaceManager m_faceManager;
+ StrategyChoiceManager m_strategyChoiceManager;
+ StatusServer m_statusServer;
+};
} // namespace nfd
int
main(int argc, char** argv)
{
- return nfd::main(argc, argv);
-}
+ using namespace nfd;
+ ProgramOptions options;
+ bool isCommandLineValid = Nfd::parseCommandLine(argc, argv, options);
+ if (!isCommandLineValid) {
+ Nfd::printUsage(std::cerr, argv[0]);
+ return 1;
+ }
+ if (options.showUsage) {
+ Nfd::printUsage(std::cout, argv[0]);
+ return 0;
+ }
+
+ try {
+ Nfd nfdInstance(options.config);
+
+ boost::asio::signal_set signalSet(getGlobalIoService());
+ signalSet.add(SIGINT);
+ signalSet.add(SIGTERM);
+ signalSet.add(SIGHUP);
+ signalSet.add(SIGUSR1);
+ signalSet.add(SIGUSR2);
+ signalSet.async_wait(bind(&Nfd::terminate, &nfdInstance, _1, _2,
+ boost::ref(signalSet)));
+
+ getGlobalIoService().run();
+ }
+ catch (boost::filesystem::filesystem_error& e) {
+ if (e.code() == boost::system::errc::permission_denied) {
+ NFD_LOG_FATAL("Permissions denied for " << e.path1() << ". "
+ << argv[0] << " should be run as superuser");
+ }
+ else {
+ NFD_LOG_FATAL(e.what());
+ }
+ return 2;
+ }
+ catch (std::exception& e) {
+ NFD_LOG_FATAL(e.what());
+ return 1;
+ }
+
+ return 0;
+}