blob: 15937848e81743b2be4ffdb92d5135ba78a1c878 [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
28#include "common.hpp"
29#include "rib-manager.hpp"
30#include "core/config-file.hpp"
Alexander Afanasyev03ea3eb2014-04-17 18:19:06 -070031#include "core/global-io.hpp"
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070032#include "core/logger.hpp"
33
34namespace nfd {
35namespace rib {
36
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -070037NFD_LOG_INIT("NRD");
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070038
39struct ProgramOptions
40{
41 bool showUsage;
42 bool showModules;
43 std::string config;
44};
45
46class Nrd : noncopyable
47{
48public:
Steve DiBenedetto34c95f72014-04-17 20:56:00 -060049 class IgnoreNfdAndLogSections
50 {
51 public:
52 void
53 operator()(const std::string& filename,
54 const std::string& sectionName,
55 const ConfigSection& section,
56 bool isDryRun)
57 {
58 // Ignore "log" and sections belonging to NFD,
59 // but raise an error if we're missing a handler for an "rib_" section.
60
61 if (sectionName.find("rib_") != 0 || sectionName == "log")
62 {
63 // do nothing
64 }
65 else
66 {
67 // missing NRD section
68 ConfigFile::throwErrorOnUnknownSection(filename, sectionName, section, isDryRun);
69 }
70 }
71 };
72
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070073 void
74 initialize(const std::string& configFile)
75 {
76 initializeLogging(configFile);
77
78 m_ribManager = make_shared<RibManager>();
79
Steve DiBenedetto34c95f72014-04-17 20:56:00 -060080 ConfigFile config((IgnoreNfdAndLogSections()));
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070081 m_ribManager->setConfigFile(config);
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -070082
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070083 // parse config file
84 config.parse(configFile, true);
85 config.parse(configFile, false);
86
87 m_ribManager->registerWithNfd();
88 m_ribManager->enableLocalControlHeader();
89 }
90
91 void
92 initializeLogging(const std::string& configFile)
93 {
Steve DiBenedetto34c95f72014-04-17 20:56:00 -060094 ConfigFile config(&ConfigFile::ignoreUnknownSection);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070095 LoggerFactory::getInstance().setConfigFile(config);
96
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070097 config.parse(configFile, true);
98 config.parse(configFile, false);
99 }
100
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700101 static void
102 printUsage(std::ostream& os, const std::string& programName)
103 {
104 os << "Usage: \n"
105 << " " << programName << " [options]\n"
106 << "\n"
107 << "Run NRD daemon\n"
108 << "\n"
109 << "Options:\n"
110 << " [--help] - print this help message\n"
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700111 << " [--config /path/to/nfd.conf] - path to configuration file "
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700112 << "(default: " << DEFAULT_CONFIG_FILE << ")\n"
113 ;
114 }
115
116 static void
117 printModules(std::ostream& os)
118 {
119 using namespace std;
120
121 os << "Available logging modules: \n";
122
123 list<string> modules(LoggerFactory::getInstance().getModules());
124 for (list<string>::const_iterator i = modules.begin(); i != modules.end(); ++i)
125 {
126 os << *i << "\n";
127 }
128 }
129
130 static bool
131 parseCommandLine(int argc, char** argv, ProgramOptions& options)
132 {
133 options.showUsage = false;
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700134 options.showModules = false;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700135 options.config = DEFAULT_CONFIG_FILE;
136
137 while (true) {
138 int optionIndex = 0;
139 static ::option longOptions[] = {
140 { "help" , no_argument , 0, 0 },
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700141 { "modules", no_argument , 0, 0 },
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700142 { "config" , required_argument, 0, 0 },
143 { 0 , 0 , 0, 0 }
144 };
145 int c = getopt_long_only(argc, argv, "", longOptions, &optionIndex);
146 if (c == -1)
147 break;
148
149 switch (c) {
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700150 case 0:
151 switch (optionIndex) {
152 case 0: // help
153 options.showUsage = true;
154 break;
155 case 1: // modules
156 options.showModules = true;
157 break;
158 case 2: // config
159 options.config = ::optarg;
160 break;
161 default:
162 return false;
163 }
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700164 break;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700165 }
166 }
167 return true;
168 }
169
170
171 void
172 terminate(const boost::system::error_code& error,
173 int signalNo,
174 boost::asio::signal_set& signalSet)
175 {
176 if (error)
177 return;
178
179 if (signalNo == SIGINT ||
180 signalNo == SIGTERM)
181 {
Alexander Afanasyev03ea3eb2014-04-17 18:19:06 -0700182 getGlobalIoService().stop();
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700183 NFD_LOG_INFO("Caught signal '" << strsignal(signalNo) << "', exiting...");
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700184 }
185 else
186 {
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700187 /// \todo May be try to reload config file
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700188 signalSet.async_wait(bind(&Nrd::terminate, this, _1, _2,
189 boost::ref(signalSet)));
190 }
191 }
192
193private:
194 shared_ptr<RibManager> m_ribManager;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700195};
196
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700197} // namespace rib
198} // namespace nfd
199
200int
201main(int argc, char** argv)
202{
203 using namespace nfd::rib;
204
205 ProgramOptions options;
206 bool isCommandLineValid = Nrd::parseCommandLine(argc, argv, options);
207 if (!isCommandLineValid) {
208 Nrd::printUsage(std::cerr, argv[0]);
209 return 1;
210 }
211 if (options.showUsage) {
212 Nrd::printUsage(std::cout, argv[0]);
213 return 0;
214 }
215
216 if (options.showModules) {
217 Nrd::printModules(std::cout);
218 return 0;
219 }
220
221 Nrd nrdInstance;
222
223 try {
224 nrdInstance.initialize(options.config);
225 }
226 catch (boost::filesystem::filesystem_error& e) {
227 if (e.code() == boost::system::errc::permission_denied) {
228 NFD_LOG_FATAL("Permissions denied for " << e.path1() << ". " <<
229 argv[0] << " should be run as superuser");
230 }
231 else {
232 NFD_LOG_FATAL(e.what());
233 }
234 return 1;
235 }
236 catch (const std::exception& e) {
237 NFD_LOG_FATAL(e.what());
238 return 2;
239 }
240
Alexander Afanasyev03ea3eb2014-04-17 18:19:06 -0700241 boost::asio::signal_set signalSet(nfd::getGlobalIoService());
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700242 signalSet.add(SIGINT);
243 signalSet.add(SIGTERM);
244 signalSet.add(SIGHUP);
245 signalSet.add(SIGUSR1);
246 signalSet.add(SIGUSR2);
247 signalSet.async_wait(bind(&Nrd::terminate, &nrdInstance, _1, _2,
248 boost::ref(signalSet)));
249
250 try {
Alexander Afanasyev03ea3eb2014-04-17 18:19:06 -0700251 nfd::getGlobalIoService().run();
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700252 }
253 catch (std::exception& e) {
254 NFD_LOG_FATAL(e.what());
255 return 3;
256 }
257
258 return 0;
259}