blob: 542d2a0ef7477f4660374c581dbbb696b6448dc4 [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>
Junxiao Shi98e29f42014-03-31 10:27:26 -07008#include <boost/filesystem.hpp>
9
Junxiao Shi09bf7c42014-01-31 11:10:25 -070010#include "core/logger.hpp"
Junxiao Shi98e29f42014-03-31 10:27:26 -070011#include "core/global-io.hpp"
Junxiao Shi09bf7c42014-01-31 11:10:25 -070012#include "fw/forwarder.hpp"
13#include "mgmt/internal-face.hpp"
Steve DiBenedetto214563c2014-02-03 19:20:36 -070014#include "mgmt/fib-manager.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070015#include "mgmt/face-manager.hpp"
Steve DiBenedetto5330e0d2014-03-05 21:52:51 -070016#include "mgmt/strategy-choice-manager.hpp"
Junxiao Shiea48d8b2014-03-16 13:53:47 -070017#include "mgmt/status-server.hpp"
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070018#include "mgmt/config-file.hpp"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080019
Junxiao Shi09bf7c42014-01-31 11:10:25 -070020namespace nfd {
21
22NFD_LOG_INIT("Main");
23
24struct ProgramOptions
Alexander Afanasyev2aa39622014-01-22 11:51:11 -080025{
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070026 bool showUsage;
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060027 bool showModules;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070028 std::string config;
Junxiao Shi09bf7c42014-01-31 11:10:25 -070029};
30
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070031class Nfd : noncopyable
Junxiao Shi09bf7c42014-01-31 11:10:25 -070032{
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070033public:
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060034
35 void
36 initialize(const std::string& configFile)
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070037 {
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060038 initializeLogging(configFile);
39
40 m_forwarder = make_shared<Forwarder>();
41
42 initializeManagement(configFile);
43 }
44
45
46 void
47 initializeLogging(const std::string& configFile)
48 {
49 ConfigFile config;
50 LoggerFactory::getInstance().setConfigFile(config);
51
52 for (size_t i = 0; i < N_SUPPORTED_CONFIG_SECTIONS; ++i)
53 {
54 if (SUPPORTED_CONFIG_SECTIONS[i] != "log")
55 {
56 config.addSectionHandler(SUPPORTED_CONFIG_SECTIONS[i],
57 bind(std::plus<int>(), 0, 0)); // no-op.
58 }
59 }
60
61 config.parse(configFile, true);
62 config.parse(configFile, false);
63 }
64
65 void
66 initializeManagement(const std::string& configFile)
67 {
68 m_internalFace = make_shared<InternalFace>();
69
70 m_fibManager = make_shared<FibManager>(boost::ref(m_forwarder->getFib()),
71 bind(&Forwarder::getFace, m_forwarder.get(), _1),
72 m_internalFace);
73
74 m_faceManager = make_shared<FaceManager>(boost::ref(m_forwarder->getFaceTable()),
75 m_internalFace);
76
77 m_strategyChoiceManager =
78 make_shared<StrategyChoiceManager>(boost::ref(m_forwarder->getStrategyChoice()),
79 m_internalFace);
80
81 m_statusServer = make_shared<StatusServer>(m_internalFace,
82 boost::ref(*m_forwarder));
83
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070084 ConfigFile config;
85 m_internalFace->getValidator().setConfigFile(config);
Junxiao Shi09bf7c42014-01-31 11:10:25 -070086
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060087 m_forwarder->addFace(m_internalFace);
Junxiao Shic041ca32014-02-25 20:01:15 -070088
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060089 m_faceManager->setConfigFile(config);
90
91 config.addSectionHandler("log", bind(std::plus<int>(), 0, 0)); // no-op
Junxiao Shic041ca32014-02-25 20:01:15 -070092
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070093 // parse config file
94 config.parse(configFile, true);
95 config.parse(configFile, false);
96
97 // add FIB entry for NFD Management Protocol
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060098 shared_ptr<fib::Entry> entry = m_forwarder->getFib().insert("/localhost/nfd").first;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070099 entry->addNextHop(m_internalFace, 0);
100 }
101
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700102 static void
103 printUsage(std::ostream& os, const std::string& programName)
104 {
105 os << "Usage: \n"
106 << " " << programName << " [options]\n"
107 << "\n"
108 << "Run NFD forwarding daemon\n"
109 << "\n"
110 << "Options:\n"
111 << " [--help] - print this help message\n"
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600112 << " [--modules] - list available logging modules\n"
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700113 << " [--config /path/to/nfd.conf] - path to configuration file "
114 << "(default: " << DEFAULT_CONFIG_FILE << ")\n"
115 ;
116 }
117
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600118 static void
119 printModules(std::ostream& os)
120 {
121 using namespace std;
122
123 os << "Available logging modules: \n";
124
125 list<string> modules(LoggerFactory::getInstance().getModules());
126 for (list<string>::const_iterator i = modules.begin(); i != modules.end(); ++i)
127 {
128 os << *i << "\n";
129 }
130 }
131
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700132 static bool
133 parseCommandLine(int argc, char** argv, ProgramOptions& options)
134 {
135 options.showUsage = false;
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600136 options.showModules = false;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700137 options.config = DEFAULT_CONFIG_FILE;
138
139 while (true) {
140 int optionIndex = 0;
141 static ::option longOptions[] = {
142 { "help" , no_argument , 0, 0 },
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600143 { "modules", no_argument , 0, 0 },
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700144 { "config" , required_argument, 0, 0 },
145 { 0 , 0 , 0, 0 }
146 };
147 int c = getopt_long_only(argc, argv, "", longOptions, &optionIndex);
148 if (c == -1)
149 break;
150
151 switch (c) {
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600152 case 0:
153 switch (optionIndex) {
154 case 0: // help
155 options.showUsage = true;
156 break;
157 case 1: // modules
158 options.showModules = true;
159 break;
160 case 2: // config
161 options.config = ::optarg;
162 break;
163 default:
164 return false;
165 }
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700166 break;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700167 }
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700168 }
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700169 return true;
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700170 }
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700171
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700172 void
173 terminate(const boost::system::error_code& error,
174 int signalNo,
175 boost::asio::signal_set& signalSet)
176 {
177 if (error)
178 return;
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700179
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700180 if (signalNo == SIGINT ||
181 signalNo == SIGTERM)
182 {
183 getGlobalIoService().stop();
184 std::cout << "Caught signal '" << strsignal(signalNo) << "', exiting..." << std::endl;
185 }
186 else
187 {
188 /// \todo May be try to reload config file (at least security section)
189 signalSet.async_wait(bind(&Nfd::terminate, this, _1, _2,
190 boost::ref(signalSet)));
191 }
Junxiao Shiea48d8b2014-03-16 13:53:47 -0700192 }
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600193
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700194private:
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600195 shared_ptr<Forwarder> m_forwarder;
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600196
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600197 shared_ptr<InternalFace> m_internalFace;
198 shared_ptr<FibManager> m_fibManager;
199 shared_ptr<FaceManager> m_faceManager;
200 shared_ptr<StrategyChoiceManager> m_strategyChoiceManager;
201 shared_ptr<StatusServer> m_statusServer;
202
203 static const std::string SUPPORTED_CONFIG_SECTIONS[];
204 static const size_t N_SUPPORTED_CONFIG_SECTIONS;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700205};
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700206
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600207const std::string Nfd::SUPPORTED_CONFIG_SECTIONS[] =
208 {
209 "log",
210 "face_system",
211 "authorizations",
212 };
213
214const size_t Nfd::N_SUPPORTED_CONFIG_SECTIONS =
215 sizeof(SUPPORTED_CONFIG_SECTIONS) / sizeof(std::string);
216
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700217} // namespace nfd
218
219int
220main(int argc, char** argv)
221{
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700222 using namespace nfd;
Junxiao Shiea48d8b2014-03-16 13:53:47 -0700223
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700224 ProgramOptions options;
225 bool isCommandLineValid = Nfd::parseCommandLine(argc, argv, options);
226 if (!isCommandLineValid) {
227 Nfd::printUsage(std::cerr, argv[0]);
228 return 1;
229 }
230 if (options.showUsage) {
231 Nfd::printUsage(std::cout, argv[0]);
232 return 0;
233 }
234
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600235 if (options.showModules) {
236 Nfd::printModules(std::cout);
237 return 0;
238 }
239
240 Nfd nfdInstance;
241
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700242 try {
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600243 nfdInstance.initialize(options.config);
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700244 }
245 catch (boost::filesystem::filesystem_error& e) {
246 if (e.code() == boost::system::errc::permission_denied) {
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600247 NFD_LOG_FATAL("Permissions denied for " << e.path1() << ". " <<
248 argv[0] << " should be run as superuser");
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700249 }
250 else {
251 NFD_LOG_FATAL(e.what());
252 }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600253 return 1;
254 }
255 catch (const std::exception& e) {
256 NFD_LOG_FATAL(e.what());
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700257 return 2;
258 }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600259
260 boost::asio::signal_set signalSet(getGlobalIoService());
261 signalSet.add(SIGINT);
262 signalSet.add(SIGTERM);
263 signalSet.add(SIGHUP);
264 signalSet.add(SIGUSR1);
265 signalSet.add(SIGUSR2);
266 signalSet.async_wait(bind(&Nfd::terminate, &nfdInstance, _1, _2,
267 boost::ref(signalSet)));
268
269 try {
270 getGlobalIoService().run();
271 }
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700272 catch (std::exception& e) {
273 NFD_LOG_FATAL(e.what());
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600274 return 3;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700275 }
276
277 return 0;
278}