blob: 0f7316704ec4ec3072793e28f36ea0c51f029b2f [file] [log] [blame]
Alexander Afanasyev2aa39622014-01-22 11:51:11 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (C) 2014 Named Data Networking Project
4 * See COPYING for copyright and distribution information.
5 */
6
Junxiao Shi09bf7c42014-01-31 11:10:25 -07007#include <getopt.h>
8#include "core/logger.hpp"
9#include "fw/forwarder.hpp"
10#include "mgmt/internal-face.hpp"
Steve DiBenedetto214563c2014-02-03 19:20:36 -070011#include "mgmt/fib-manager.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070012#include "mgmt/face-manager.hpp"
Steve DiBenedetto5330e0d2014-03-05 21:52:51 -070013#include "mgmt/strategy-choice-manager.hpp"
Junxiao Shiea48d8b2014-03-16 13:53:47 -070014#include "mgmt/status-server.hpp"
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070015#include "mgmt/config-file.hpp"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080016
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -060017#include <boost/filesystem.hpp>
Junxiao Shi09bf7c42014-01-31 11:10:25 -070018
19namespace nfd {
20
21NFD_LOG_INIT("Main");
22
23struct ProgramOptions
Alexander Afanasyev2aa39622014-01-22 11:51:11 -080024{
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070025 bool showUsage;
26 std::string config;
Junxiao Shi09bf7c42014-01-31 11:10:25 -070027};
28
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070029class Nfd : noncopyable
Junxiao Shi09bf7c42014-01-31 11:10:25 -070030{
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070031public:
32 explicit
33 Nfd(const std::string& configFile)
34 : m_internalFace(new InternalFace())
35 , m_fibManager(m_forwarder.getFib(),
36 bind(&Forwarder::getFace, &m_forwarder, _1),
37 m_internalFace)
38 , m_faceManager(m_forwarder.getFaceTable(), m_internalFace)
39 , m_strategyChoiceManager(m_forwarder.getStrategyChoice(), m_internalFace)
40 , m_statusServer(m_internalFace, m_forwarder)
41 {
42 ConfigFile config;
43 m_internalFace->getValidator().setConfigFile(config);
Junxiao Shi09bf7c42014-01-31 11:10:25 -070044
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070045 m_forwarder.addFace(m_internalFace);
Junxiao Shic041ca32014-02-25 20:01:15 -070046
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070047 m_faceManager.setConfigFile(config);
Junxiao Shic041ca32014-02-25 20:01:15 -070048
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070049 // parse config file
50 config.parse(configFile, true);
51 config.parse(configFile, false);
52
53 // add FIB entry for NFD Management Protocol
54 shared_ptr<fib::Entry> entry = m_forwarder.getFib().insert("/localhost/nfd").first;
55 entry->addNextHop(m_internalFace, 0);
56 }
57
58
59 static void
60 printUsage(std::ostream& os, const std::string& programName)
61 {
62 os << "Usage: \n"
63 << " " << programName << " [options]\n"
64 << "\n"
65 << "Run NFD forwarding daemon\n"
66 << "\n"
67 << "Options:\n"
68 << " [--help] - print this help message\n"
69 << " [--config /path/to/nfd.conf] - path to configuration file "
70 << "(default: " << DEFAULT_CONFIG_FILE << ")\n"
71 ;
72 }
73
74 static bool
75 parseCommandLine(int argc, char** argv, ProgramOptions& options)
76 {
77 options.showUsage = false;
78 options.config = DEFAULT_CONFIG_FILE;
79
80 while (true) {
81 int optionIndex = 0;
82 static ::option longOptions[] = {
83 { "help" , no_argument , 0, 0 },
84 { "config" , required_argument, 0, 0 },
85 { 0 , 0 , 0, 0 }
86 };
87 int c = getopt_long_only(argc, argv, "", longOptions, &optionIndex);
88 if (c == -1)
89 break;
90
91 switch (c) {
Junxiao Shi09bf7c42014-01-31 11:10:25 -070092 case 0:
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070093 switch (optionIndex) {
94 case 0: // help
95 options.showUsage = true;
96 break;
97 case 1: // config
98 options.config = ::optarg;
99 break;
100 default:
101 return false;
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700102 }
103 break;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700104 }
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700105 }
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700106
107 return true;
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700108 }
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700109
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700110 void
111 terminate(const boost::system::error_code& error,
112 int signalNo,
113 boost::asio::signal_set& signalSet)
114 {
115 if (error)
116 return;
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700117
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700118 if (signalNo == SIGINT ||
119 signalNo == SIGTERM)
120 {
121 getGlobalIoService().stop();
122 std::cout << "Caught signal '" << strsignal(signalNo) << "', exiting..." << std::endl;
123 }
124 else
125 {
126 /// \todo May be try to reload config file (at least security section)
127 signalSet.async_wait(bind(&Nfd::terminate, this, _1, _2,
128 boost::ref(signalSet)));
129 }
Junxiao Shiea48d8b2014-03-16 13:53:47 -0700130 }
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600131
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700132private:
133 Forwarder m_forwarder;
134 shared_ptr<InternalFace> m_internalFace;
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600135
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700136 FibManager m_fibManager;
137 FaceManager m_faceManager;
138 StrategyChoiceManager m_strategyChoiceManager;
139 StatusServer m_statusServer;
140};
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700141
142} // namespace nfd
143
144int
145main(int argc, char** argv)
146{
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700147 using namespace nfd;
Junxiao Shiea48d8b2014-03-16 13:53:47 -0700148
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700149 ProgramOptions options;
150 bool isCommandLineValid = Nfd::parseCommandLine(argc, argv, options);
151 if (!isCommandLineValid) {
152 Nfd::printUsage(std::cerr, argv[0]);
153 return 1;
154 }
155 if (options.showUsage) {
156 Nfd::printUsage(std::cout, argv[0]);
157 return 0;
158 }
159
160 try {
161 Nfd nfdInstance(options.config);
162
163 boost::asio::signal_set signalSet(getGlobalIoService());
164 signalSet.add(SIGINT);
165 signalSet.add(SIGTERM);
166 signalSet.add(SIGHUP);
167 signalSet.add(SIGUSR1);
168 signalSet.add(SIGUSR2);
169 signalSet.async_wait(bind(&Nfd::terminate, &nfdInstance, _1, _2,
170 boost::ref(signalSet)));
171
172 getGlobalIoService().run();
173 }
174 catch (boost::filesystem::filesystem_error& e) {
175 if (e.code() == boost::system::errc::permission_denied) {
176 NFD_LOG_FATAL("Permissions denied for " << e.path1() << ". "
177 << argv[0] << " should be run as superuser");
178 }
179 else {
180 NFD_LOG_FATAL(e.what());
181 }
182 return 2;
183 }
184 catch (std::exception& e) {
185 NFD_LOG_FATAL(e.what());
186 return 1;
187 }
188
189 return 0;
190}