blob: d74ed8d40ab7cb2eea3e4c0cb50ebb0d37005ba8 [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
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070075 void
76 initialize(const std::string& configFile)
77 {
78 initializeLogging(configFile);
79
80 m_ribManager = make_shared<RibManager>();
81
Steve DiBenedetto34c95f72014-04-17 20:56:00 -060082 ConfigFile config((IgnoreNfdAndLogSections()));
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070083 m_ribManager->setConfigFile(config);
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -070084
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070085 // parse config file
86 config.parse(configFile, true);
87 config.parse(configFile, false);
88
89 m_ribManager->registerWithNfd();
90 m_ribManager->enableLocalControlHeader();
91 }
92
93 void
94 initializeLogging(const std::string& configFile)
95 {
Steve DiBenedetto34c95f72014-04-17 20:56:00 -060096 ConfigFile config(&ConfigFile::ignoreUnknownSection);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070097 LoggerFactory::getInstance().setConfigFile(config);
98
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070099 config.parse(configFile, true);
100 config.parse(configFile, false);
101 }
102
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700103 static void
104 printUsage(std::ostream& os, const std::string& programName)
105 {
106 os << "Usage: \n"
107 << " " << programName << " [options]\n"
108 << "\n"
109 << "Run NRD daemon\n"
110 << "\n"
111 << "Options:\n"
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700112 << " [--help] - print this help message\n"
113 << " [--version] - print version and exit\n"
114 << " [--modules] - list available logging modules\n"
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700115 << " [--config /path/to/nfd.conf] - path to configuration file "
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700116 << "(default: " << DEFAULT_CONFIG_FILE << ")\n"
117 ;
118 }
119
120 static void
121 printModules(std::ostream& os)
122 {
123 using namespace std;
124
125 os << "Available logging modules: \n";
126
127 list<string> modules(LoggerFactory::getInstance().getModules());
128 for (list<string>::const_iterator i = modules.begin(); i != modules.end(); ++i)
129 {
130 os << *i << "\n";
131 }
132 }
133
134 static bool
135 parseCommandLine(int argc, char** argv, ProgramOptions& options)
136 {
137 options.showUsage = false;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700138 options.showVersion = false;
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700139 options.showModules = false;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700140 options.config = DEFAULT_CONFIG_FILE;
141
142 while (true) {
143 int optionIndex = 0;
144 static ::option longOptions[] = {
145 { "help" , no_argument , 0, 0 },
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700146 { "modules", no_argument , 0, 0 },
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700147 { "config" , required_argument, 0, 0 },
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700148 { "version", no_argument , 0, 0 },
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700149 { 0 , 0 , 0, 0 }
150 };
151 int c = getopt_long_only(argc, argv, "", longOptions, &optionIndex);
152 if (c == -1)
153 break;
154
155 switch (c) {
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700156 case 0:
157 switch (optionIndex) {
158 case 0: // help
159 options.showUsage = true;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700160 break;
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700161 case 1: // modules
162 options.showModules = true;
163 break;
164 case 2: // config
165 options.config = ::optarg;
166 break;
167 case 3: // version
168 options.showVersion = true;
169 break;
170 default:
171 return false;
172 }
173 break;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700174 }
175 }
176 return true;
177 }
178
179
180 void
181 terminate(const boost::system::error_code& error,
182 int signalNo,
183 boost::asio::signal_set& signalSet)
184 {
185 if (error)
186 return;
187
188 if (signalNo == SIGINT ||
189 signalNo == SIGTERM)
190 {
Alexander Afanasyev03ea3eb2014-04-17 18:19:06 -0700191 getGlobalIoService().stop();
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700192 NFD_LOG_INFO("Caught signal '" << strsignal(signalNo) << "', exiting...");
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700193 }
194 else
195 {
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700196 /// \todo May be try to reload config file
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700197 signalSet.async_wait(bind(&Nrd::terminate, this, _1, _2,
198 boost::ref(signalSet)));
199 }
200 }
201
202private:
203 shared_ptr<RibManager> m_ribManager;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700204};
205
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700206} // namespace rib
207} // namespace nfd
208
209int
210main(int argc, char** argv)
211{
212 using namespace nfd::rib;
213
214 ProgramOptions options;
215 bool isCommandLineValid = Nrd::parseCommandLine(argc, argv, options);
216 if (!isCommandLineValid) {
217 Nrd::printUsage(std::cerr, argv[0]);
218 return 1;
219 }
220 if (options.showUsage) {
221 Nrd::printUsage(std::cout, argv[0]);
222 return 0;
223 }
224
225 if (options.showModules) {
226 Nrd::printModules(std::cout);
227 return 0;
228 }
229
Alexander Afanasyevb47d5382014-05-05 14:35:03 -0700230 if (options.showVersion) {
231 std::cout << NFD_VERSION_BUILD_STRING << std::endl;
232 return 0;
233 }
234
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700235 Nrd nrdInstance;
236
237 try {
238 nrdInstance.initialize(options.config);
239 }
240 catch (boost::filesystem::filesystem_error& e) {
241 if (e.code() == boost::system::errc::permission_denied) {
242 NFD_LOG_FATAL("Permissions denied for " << e.path1() << ". " <<
243 argv[0] << " should be run as superuser");
244 }
245 else {
246 NFD_LOG_FATAL(e.what());
247 }
248 return 1;
249 }
250 catch (const std::exception& e) {
251 NFD_LOG_FATAL(e.what());
252 return 2;
253 }
254
Alexander Afanasyev03ea3eb2014-04-17 18:19:06 -0700255 boost::asio::signal_set signalSet(nfd::getGlobalIoService());
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700256 signalSet.add(SIGINT);
257 signalSet.add(SIGTERM);
258 signalSet.add(SIGHUP);
259 signalSet.add(SIGUSR1);
260 signalSet.add(SIGUSR2);
261 signalSet.async_wait(bind(&Nrd::terminate, &nrdInstance, _1, _2,
262 boost::ref(signalSet)));
263
264 try {
Alexander Afanasyev03ea3eb2014-04-17 18:19:06 -0700265 nfd::getGlobalIoService().run();
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700266 }
267 catch (std::exception& e) {
268 NFD_LOG_FATAL(e.what());
269 return 3;
270 }
271
272 return 0;
273}