blob: de9511e8bb028b526f3109d3bffdb48c3598bae7 [file] [log] [blame]
Alexander Afanasyev2aa39622014-01-22 11:51:11 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev9bcbc7c2014-04-06 19:37:37 -07003 * Copyright (c) 2014 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 *
10 * This file is part of NFD (Named Data Networking Forwarding Daemon).
11 * See AUTHORS.md for complete list of NFD authors and contributors.
12 *
13 * NFD is free software: you can redistribute it and/or modify it under the terms
14 * of the GNU General Public License as published by the Free Software Foundation,
15 * either version 3 of the License, or (at your option) any later version.
16 *
17 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
18 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
19 * PURPOSE. See the GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along with
22 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
23 **/
Alexander Afanasyev2aa39622014-01-22 11:51:11 -080024
Junxiao Shi09bf7c42014-01-31 11:10:25 -070025#include <getopt.h>
Junxiao Shi98e29f42014-03-31 10:27:26 -070026#include <boost/filesystem.hpp>
27
Junxiao Shi09bf7c42014-01-31 11:10:25 -070028#include "core/logger.hpp"
Junxiao Shi98e29f42014-03-31 10:27:26 -070029#include "core/global-io.hpp"
Junxiao Shi09bf7c42014-01-31 11:10:25 -070030#include "fw/forwarder.hpp"
31#include "mgmt/internal-face.hpp"
Steve DiBenedetto214563c2014-02-03 19:20:36 -070032#include "mgmt/fib-manager.hpp"
Steve DiBenedettoabe9e972014-02-20 15:37:04 -070033#include "mgmt/face-manager.hpp"
Steve DiBenedetto5330e0d2014-03-05 21:52:51 -070034#include "mgmt/strategy-choice-manager.hpp"
Junxiao Shiea48d8b2014-03-16 13:53:47 -070035#include "mgmt/status-server.hpp"
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -070036#include "mgmt/config-file.hpp"
Alexander Afanasyevc78b1412014-02-19 14:08:26 -080037
Junxiao Shi09bf7c42014-01-31 11:10:25 -070038namespace nfd {
39
40NFD_LOG_INIT("Main");
41
42struct ProgramOptions
Alexander Afanasyev2aa39622014-01-22 11:51:11 -080043{
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070044 bool showUsage;
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060045 bool showModules;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070046 std::string config;
Junxiao Shi09bf7c42014-01-31 11:10:25 -070047};
48
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070049class Nfd : noncopyable
Junxiao Shi09bf7c42014-01-31 11:10:25 -070050{
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070051public:
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060052
53 void
54 initialize(const std::string& configFile)
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -070055 {
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -060056 initializeLogging(configFile);
57
58 m_forwarder = make_shared<Forwarder>();
59
60 initializeManagement(configFile);
61 }
62
63
64 void
65 initializeLogging(const std::string& configFile)
66 {
67 ConfigFile config;
68 LoggerFactory::getInstance().setConfigFile(config);
69
70 for (size_t i = 0; i < N_SUPPORTED_CONFIG_SECTIONS; ++i)
71 {
72 if (SUPPORTED_CONFIG_SECTIONS[i] != "log")
73 {
74 config.addSectionHandler(SUPPORTED_CONFIG_SECTIONS[i],
75 bind(std::plus<int>(), 0, 0)); // no-op.
76 }
77 }
78
79 config.parse(configFile, true);
80 config.parse(configFile, false);
81 }
82
83 void
84 initializeManagement(const std::string& configFile)
85 {
86 m_internalFace = make_shared<InternalFace>();
87
88 m_fibManager = make_shared<FibManager>(boost::ref(m_forwarder->getFib()),
89 bind(&Forwarder::getFace, m_forwarder.get(), _1),
90 m_internalFace);
91
92 m_faceManager = make_shared<FaceManager>(boost::ref(m_forwarder->getFaceTable()),
93 m_internalFace);
94
95 m_strategyChoiceManager =
96 make_shared<StrategyChoiceManager>(boost::ref(m_forwarder->getStrategyChoice()),
97 m_internalFace);
98
99 m_statusServer = make_shared<StatusServer>(m_internalFace,
100 boost::ref(*m_forwarder));
101
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700102 ConfigFile config;
103 m_internalFace->getValidator().setConfigFile(config);
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700104
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600105 m_forwarder->addFace(m_internalFace);
Junxiao Shic041ca32014-02-25 20:01:15 -0700106
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600107 m_faceManager->setConfigFile(config);
108
109 config.addSectionHandler("log", bind(std::plus<int>(), 0, 0)); // no-op
Junxiao Shic041ca32014-02-25 20:01:15 -0700110
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700111 // parse config file
112 config.parse(configFile, true);
113 config.parse(configFile, false);
114
115 // add FIB entry for NFD Management Protocol
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600116 shared_ptr<fib::Entry> entry = m_forwarder->getFib().insert("/localhost/nfd").first;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700117 entry->addNextHop(m_internalFace, 0);
118 }
119
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700120 static void
121 printUsage(std::ostream& os, const std::string& programName)
122 {
123 os << "Usage: \n"
124 << " " << programName << " [options]\n"
125 << "\n"
126 << "Run NFD forwarding daemon\n"
127 << "\n"
128 << "Options:\n"
129 << " [--help] - print this help message\n"
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600130 << " [--modules] - list available logging modules\n"
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700131 << " [--config /path/to/nfd.conf] - path to configuration file "
132 << "(default: " << DEFAULT_CONFIG_FILE << ")\n"
133 ;
134 }
135
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600136 static void
137 printModules(std::ostream& os)
138 {
139 using namespace std;
140
141 os << "Available logging modules: \n";
142
143 list<string> modules(LoggerFactory::getInstance().getModules());
144 for (list<string>::const_iterator i = modules.begin(); i != modules.end(); ++i)
145 {
146 os << *i << "\n";
147 }
148 }
149
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700150 static bool
151 parseCommandLine(int argc, char** argv, ProgramOptions& options)
152 {
153 options.showUsage = false;
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600154 options.showModules = false;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700155 options.config = DEFAULT_CONFIG_FILE;
156
157 while (true) {
158 int optionIndex = 0;
159 static ::option longOptions[] = {
160 { "help" , no_argument , 0, 0 },
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600161 { "modules", no_argument , 0, 0 },
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700162 { "config" , required_argument, 0, 0 },
163 { 0 , 0 , 0, 0 }
164 };
165 int c = getopt_long_only(argc, argv, "", longOptions, &optionIndex);
166 if (c == -1)
167 break;
168
169 switch (c) {
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600170 case 0:
171 switch (optionIndex) {
172 case 0: // help
173 options.showUsage = true;
174 break;
175 case 1: // modules
176 options.showModules = true;
177 break;
178 case 2: // config
179 options.config = ::optarg;
180 break;
181 default:
182 return false;
183 }
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700184 break;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700185 }
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700186 }
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700187 return true;
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700188 }
Steve DiBenedetto2c2b8892014-02-27 11:46:48 -0700189
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700190 void
191 terminate(const boost::system::error_code& error,
192 int signalNo,
193 boost::asio::signal_set& signalSet)
194 {
195 if (error)
196 return;
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700197
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700198 if (signalNo == SIGINT ||
199 signalNo == SIGTERM)
200 {
201 getGlobalIoService().stop();
202 std::cout << "Caught signal '" << strsignal(signalNo) << "', exiting..." << std::endl;
203 }
204 else
205 {
206 /// \todo May be try to reload config file (at least security section)
207 signalSet.async_wait(bind(&Nfd::terminate, this, _1, _2,
208 boost::ref(signalSet)));
209 }
Junxiao Shiea48d8b2014-03-16 13:53:47 -0700210 }
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600211
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700212private:
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600213 shared_ptr<Forwarder> m_forwarder;
Steve DiBenedetto84da5bf2014-03-11 14:51:29 -0600214
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600215 shared_ptr<InternalFace> m_internalFace;
216 shared_ptr<FibManager> m_fibManager;
217 shared_ptr<FaceManager> m_faceManager;
218 shared_ptr<StrategyChoiceManager> m_strategyChoiceManager;
219 shared_ptr<StatusServer> m_statusServer;
220
221 static const std::string SUPPORTED_CONFIG_SECTIONS[];
222 static const size_t N_SUPPORTED_CONFIG_SECTIONS;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700223};
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700224
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600225const std::string Nfd::SUPPORTED_CONFIG_SECTIONS[] =
226 {
227 "log",
228 "face_system",
229 "authorizations",
230 };
231
232const size_t Nfd::N_SUPPORTED_CONFIG_SECTIONS =
233 sizeof(SUPPORTED_CONFIG_SECTIONS) / sizeof(std::string);
234
Junxiao Shi09bf7c42014-01-31 11:10:25 -0700235} // namespace nfd
236
237int
238main(int argc, char** argv)
239{
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700240 using namespace nfd;
Junxiao Shiea48d8b2014-03-16 13:53:47 -0700241
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700242 ProgramOptions options;
243 bool isCommandLineValid = Nfd::parseCommandLine(argc, argv, options);
244 if (!isCommandLineValid) {
245 Nfd::printUsage(std::cerr, argv[0]);
246 return 1;
247 }
248 if (options.showUsage) {
249 Nfd::printUsage(std::cout, argv[0]);
250 return 0;
251 }
252
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600253 if (options.showModules) {
254 Nfd::printModules(std::cout);
255 return 0;
256 }
257
258 Nfd nfdInstance;
259
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700260 try {
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600261 nfdInstance.initialize(options.config);
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700262 }
263 catch (boost::filesystem::filesystem_error& e) {
264 if (e.code() == boost::system::errc::permission_denied) {
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600265 NFD_LOG_FATAL("Permissions denied for " << e.path1() << ". " <<
266 argv[0] << " should be run as superuser");
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700267 }
268 else {
269 NFD_LOG_FATAL(e.what());
270 }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600271 return 1;
272 }
273 catch (const std::exception& e) {
274 NFD_LOG_FATAL(e.what());
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700275 return 2;
276 }
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600277
278 boost::asio::signal_set signalSet(getGlobalIoService());
279 signalSet.add(SIGINT);
280 signalSet.add(SIGTERM);
281 signalSet.add(SIGHUP);
282 signalSet.add(SIGUSR1);
283 signalSet.add(SIGUSR2);
284 signalSet.async_wait(bind(&Nfd::terminate, &nfdInstance, _1, _2,
285 boost::ref(signalSet)));
286
287 try {
288 getGlobalIoService().run();
289 }
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700290 catch (std::exception& e) {
291 NFD_LOG_FATAL(e.what());
Steve DiBenedettobf6a93d2014-03-21 14:03:02 -0600292 return 3;
Alexander Afanasyev5a4388a2014-03-27 18:02:55 -0700293 }
294
295 return 0;
296}