blob: 452b8a9a29c0563871e7351cd45dc360be9eca9a [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"
31#include "core/logger.hpp"
32
33namespace nfd {
34namespace rib {
35
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -070036NFD_LOG_INIT("NRD");
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070037
38struct ProgramOptions
39{
40 bool showUsage;
41 bool showModules;
42 std::string config;
43};
44
45class Nrd : noncopyable
46{
47public:
Steve DiBenedetto34c95f72014-04-17 20:56:00 -060048 class IgnoreNfdAndLogSections
49 {
50 public:
51 void
52 operator()(const std::string& filename,
53 const std::string& sectionName,
54 const ConfigSection& section,
55 bool isDryRun)
56 {
57 // Ignore "log" and sections belonging to NFD,
58 // but raise an error if we're missing a handler for an "rib_" section.
59
60 if (sectionName.find("rib_") != 0 || sectionName == "log")
61 {
62 // do nothing
63 }
64 else
65 {
66 // missing NRD section
67 ConfigFile::throwErrorOnUnknownSection(filename, sectionName, section, isDryRun);
68 }
69 }
70 };
71
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070072 void
73 initialize(const std::string& configFile)
74 {
75 initializeLogging(configFile);
76
77 m_ribManager = make_shared<RibManager>();
78
Steve DiBenedetto34c95f72014-04-17 20:56:00 -060079 ConfigFile config((IgnoreNfdAndLogSections()));
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070080 m_ribManager->setConfigFile(config);
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -070081
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070082 // parse config file
83 config.parse(configFile, true);
84 config.parse(configFile, false);
85
86 m_ribManager->registerWithNfd();
87 m_ribManager->enableLocalControlHeader();
88 }
89
90 void
91 initializeLogging(const std::string& configFile)
92 {
Steve DiBenedetto34c95f72014-04-17 20:56:00 -060093 ConfigFile config(&ConfigFile::ignoreUnknownSection);
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070094 LoggerFactory::getInstance().setConfigFile(config);
95
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070096 config.parse(configFile, true);
97 config.parse(configFile, false);
98 }
99
100 boost::asio::io_service&
101 getIoService()
102 {
103 return m_ribManager->getIoService();
104 }
105
106 static void
107 printUsage(std::ostream& os, const std::string& programName)
108 {
109 os << "Usage: \n"
110 << " " << programName << " [options]\n"
111 << "\n"
112 << "Run NRD daemon\n"
113 << "\n"
114 << "Options:\n"
115 << " [--help] - print this help message\n"
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700116 << " [--config /path/to/nfd.conf] - path to configuration file "
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700117 << "(default: " << DEFAULT_CONFIG_FILE << ")\n"
118 ;
119 }
120
121 static void
122 printModules(std::ostream& os)
123 {
124 using namespace std;
125
126 os << "Available logging modules: \n";
127
128 list<string> modules(LoggerFactory::getInstance().getModules());
129 for (list<string>::const_iterator i = modules.begin(); i != modules.end(); ++i)
130 {
131 os << *i << "\n";
132 }
133 }
134
135 static bool
136 parseCommandLine(int argc, char** argv, ProgramOptions& options)
137 {
138 options.showUsage = 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 },
148 { 0 , 0 , 0, 0 }
149 };
150 int c = getopt_long_only(argc, argv, "", longOptions, &optionIndex);
151 if (c == -1)
152 break;
153
154 switch (c) {
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700155 case 0:
156 switch (optionIndex) {
157 case 0: // help
158 options.showUsage = true;
159 break;
160 case 1: // modules
161 options.showModules = true;
162 break;
163 case 2: // config
164 options.config = ::optarg;
165 break;
166 default:
167 return false;
168 }
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700169 break;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700170 }
171 }
172 return true;
173 }
174
175
176 void
177 terminate(const boost::system::error_code& error,
178 int signalNo,
179 boost::asio::signal_set& signalSet)
180 {
181 if (error)
182 return;
183
184 if (signalNo == SIGINT ||
185 signalNo == SIGTERM)
186 {
187 getIoService().stop();
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700188 NFD_LOG_INFO("Caught signal '" << strsignal(signalNo) << "', exiting...");
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700189 }
190 else
191 {
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700192 /// \todo May be try to reload config file
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700193 signalSet.async_wait(bind(&Nrd::terminate, this, _1, _2,
194 boost::ref(signalSet)));
195 }
196 }
197
198private:
199 shared_ptr<RibManager> m_ribManager;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700200};
201
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700202} // namespace rib
203} // namespace nfd
204
205int
206main(int argc, char** argv)
207{
208 using namespace nfd::rib;
209
210 ProgramOptions options;
211 bool isCommandLineValid = Nrd::parseCommandLine(argc, argv, options);
212 if (!isCommandLineValid) {
213 Nrd::printUsage(std::cerr, argv[0]);
214 return 1;
215 }
216 if (options.showUsage) {
217 Nrd::printUsage(std::cout, argv[0]);
218 return 0;
219 }
220
221 if (options.showModules) {
222 Nrd::printModules(std::cout);
223 return 0;
224 }
225
226 Nrd nrdInstance;
227
228 try {
229 nrdInstance.initialize(options.config);
230 }
231 catch (boost::filesystem::filesystem_error& e) {
232 if (e.code() == boost::system::errc::permission_denied) {
233 NFD_LOG_FATAL("Permissions denied for " << e.path1() << ". " <<
234 argv[0] << " should be run as superuser");
235 }
236 else {
237 NFD_LOG_FATAL(e.what());
238 }
239 return 1;
240 }
241 catch (const std::exception& e) {
242 NFD_LOG_FATAL(e.what());
243 return 2;
244 }
245
246 boost::asio::signal_set signalSet(nrdInstance.getIoService());
247 signalSet.add(SIGINT);
248 signalSet.add(SIGTERM);
249 signalSet.add(SIGHUP);
250 signalSet.add(SIGUSR1);
251 signalSet.add(SIGUSR2);
252 signalSet.async_wait(bind(&Nrd::terminate, &nrdInstance, _1, _2,
253 boost::ref(signalSet)));
254
255 try {
256 nrdInstance.getIoService().run();
257 }
258 catch (std::exception& e) {
259 NFD_LOG_FATAL(e.what());
260 return 3;
261 }
262
263 return 0;
264}