blob: b123b0450d03dfddf068e05ebe59cdb8b91feb90 [file] [log] [blame]
Alexander Afanasyev3ecec502014-04-16 13:42:44 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * 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 * The University of Memphis
10 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24 **/
25
26#include <getopt.h>
27
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070028#include "version.hpp"
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070029#include "common.hpp"
30#include "rib-manager.hpp"
31#include "core/config-file.hpp"
Alexander Afanasyev03ea3eb2014-04-17 18:19:06 -070032#include "core/global-io.hpp"
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070033#include "core/logger.hpp"
34
35namespace nfd {
36namespace rib {
37
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -070038NFD_LOG_INIT("NRD");
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070039
40struct ProgramOptions
41{
42 bool showUsage;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -070043 bool showVersion;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070044 bool showModules;
45 std::string config;
46};
47
48class Nrd : noncopyable
49{
50public:
Steve DiBenedetto34c95f72014-04-17 20:56:00 -060051 class IgnoreNfdAndLogSections
52 {
53 public:
54 void
55 operator()(const std::string& filename,
56 const std::string& sectionName,
57 const ConfigSection& section,
58 bool isDryRun)
59 {
60 // Ignore "log" and sections belonging to NFD,
61 // but raise an error if we're missing a handler for an "rib_" section.
62
63 if (sectionName.find("rib_") != 0 || sectionName == "log")
64 {
65 // do nothing
66 }
67 else
68 {
69 // missing NRD section
70 ConfigFile::throwErrorOnUnknownSection(filename, sectionName, section, isDryRun);
71 }
72 }
73 };
74
Vince Lehman72446ec2014-07-09 10:50:02 -050075 Nrd()
76 : m_face(getGlobalIoService())
77 {
78 }
79
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070080 void
81 initialize(const std::string& configFile)
82 {
83 initializeLogging(configFile);
84
Vince Lehman72446ec2014-07-09 10:50:02 -050085 m_ribManager = make_shared<RibManager>(ndn::ref(m_face));
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070086
Steve DiBenedetto34c95f72014-04-17 20:56:00 -060087 ConfigFile config((IgnoreNfdAndLogSections()));
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070088 m_ribManager->setConfigFile(config);
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -070089
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070090 // parse config file
91 config.parse(configFile, true);
92 config.parse(configFile, false);
93
94 m_ribManager->registerWithNfd();
95 m_ribManager->enableLocalControlHeader();
96 }
97
98 void
99 initializeLogging(const std::string& configFile)
100 {
Steve DiBenedetto34c95f72014-04-17 20:56:00 -0600101 ConfigFile config(&ConfigFile::ignoreUnknownSection);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700102 LoggerFactory::getInstance().setConfigFile(config);
103
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700104 config.parse(configFile, true);
105 config.parse(configFile, false);
106 }
107
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700108 static void
109 printUsage(std::ostream& os, const std::string& programName)
110 {
111 os << "Usage: \n"
112 << " " << programName << " [options]\n"
113 << "\n"
114 << "Run NRD daemon\n"
115 << "\n"
116 << "Options:\n"
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700117 << " [--help] - print this help message\n"
118 << " [--version] - print version and exit\n"
119 << " [--modules] - list available logging modules\n"
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700120 << " [--config /path/to/nfd.conf] - path to configuration file "
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700121 << "(default: " << DEFAULT_CONFIG_FILE << ")\n"
122 ;
123 }
124
125 static void
126 printModules(std::ostream& os)
127 {
128 using namespace std;
129
130 os << "Available logging modules: \n";
131
132 list<string> modules(LoggerFactory::getInstance().getModules());
133 for (list<string>::const_iterator i = modules.begin(); i != modules.end(); ++i)
134 {
135 os << *i << "\n";
136 }
137 }
138
139 static bool
140 parseCommandLine(int argc, char** argv, ProgramOptions& options)
141 {
142 options.showUsage = false;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700143 options.showVersion = false;
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700144 options.showModules = false;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700145 options.config = DEFAULT_CONFIG_FILE;
146
147 while (true) {
148 int optionIndex = 0;
149 static ::option longOptions[] = {
150 { "help" , no_argument , 0, 0 },
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700151 { "modules", no_argument , 0, 0 },
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700152 { "config" , required_argument, 0, 0 },
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700153 { "version", no_argument , 0, 0 },
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700154 { 0 , 0 , 0, 0 }
155 };
156 int c = getopt_long_only(argc, argv, "", longOptions, &optionIndex);
157 if (c == -1)
158 break;
159
160 switch (c) {
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700161 case 0:
162 switch (optionIndex) {
163 case 0: // help
164 options.showUsage = true;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700165 break;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700166 case 1: // modules
167 options.showModules = true;
168 break;
169 case 2: // config
170 options.config = ::optarg;
171 break;
172 case 3: // version
173 options.showVersion = true;
174 break;
175 default:
176 return false;
177 }
178 break;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700179 }
180 }
181 return true;
182 }
183
184
185 void
186 terminate(const boost::system::error_code& error,
187 int signalNo,
188 boost::asio::signal_set& signalSet)
189 {
190 if (error)
191 return;
192
193 if (signalNo == SIGINT ||
194 signalNo == SIGTERM)
195 {
Alexander Afanasyev03ea3eb2014-04-17 18:19:06 -0700196 getGlobalIoService().stop();
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700197 NFD_LOG_INFO("Caught signal '" << strsignal(signalNo) << "', exiting...");
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700198 }
199 else
200 {
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700201 /// \todo May be try to reload config file
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700202 signalSet.async_wait(bind(&Nrd::terminate, this, _1, _2,
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700203 ref(signalSet)));
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700204 }
205 }
206
207private:
208 shared_ptr<RibManager> m_ribManager;
Vince Lehman72446ec2014-07-09 10:50:02 -0500209 ndn::Face m_face;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700210};
211
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700212} // namespace rib
213} // namespace nfd
214
215int
216main(int argc, char** argv)
217{
218 using namespace nfd::rib;
219
220 ProgramOptions options;
221 bool isCommandLineValid = Nrd::parseCommandLine(argc, argv, options);
222 if (!isCommandLineValid) {
223 Nrd::printUsage(std::cerr, argv[0]);
224 return 1;
225 }
226 if (options.showUsage) {
227 Nrd::printUsage(std::cout, argv[0]);
228 return 0;
229 }
230
231 if (options.showModules) {
232 Nrd::printModules(std::cout);
233 return 0;
234 }
235
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700236 if (options.showVersion) {
237 std::cout << NFD_VERSION_BUILD_STRING << std::endl;
238 return 0;
239 }
240
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700241 Nrd nrdInstance;
242
243 try {
244 nrdInstance.initialize(options.config);
245 }
246 catch (boost::filesystem::filesystem_error& e) {
247 if (e.code() == boost::system::errc::permission_denied) {
248 NFD_LOG_FATAL("Permissions denied for " << e.path1() << ". " <<
249 argv[0] << " should be run as superuser");
250 }
251 else {
252 NFD_LOG_FATAL(e.what());
253 }
254 return 1;
255 }
256 catch (const std::exception& e) {
257 NFD_LOG_FATAL(e.what());
258 return 2;
259 }
260
Alexander Afanasyev03ea3eb2014-04-17 18:19:06 -0700261 boost::asio::signal_set signalSet(nfd::getGlobalIoService());
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700262 signalSet.add(SIGINT);
263 signalSet.add(SIGTERM);
264 signalSet.add(SIGHUP);
265 signalSet.add(SIGUSR1);
266 signalSet.add(SIGUSR2);
267 signalSet.async_wait(bind(&Nrd::terminate, &nrdInstance, _1, _2,
Alexander Afanasyevf6980282014-05-13 18:28:40 -0700268 ndn::ref(signalSet)));
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700269
270 try {
Alexander Afanasyev03ea3eb2014-04-17 18:19:06 -0700271 nfd::getGlobalIoService().run();
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700272 }
273 catch (std::exception& e) {
274 NFD_LOG_FATAL(e.what());
275 return 3;
276 }
277
278 return 0;
279}