blob: 7598d6c6b8df2942d1e1771638a62f063f1e3956 [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:
48 void
49 initialize(const std::string& configFile)
50 {
51 initializeLogging(configFile);
52
53 m_ribManager = make_shared<RibManager>();
54
55 ConfigFile config;
56 m_ribManager->setConfigFile(config);
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -070057
58 for (size_t i = 0; i < N_SUPPORTED_CONFIG_SECTIONS; ++i)
59 {
60 if (SUPPORTED_CONFIG_SECTIONS[i] != "rib_security")
61 {
62 config.addSectionHandler(SUPPORTED_CONFIG_SECTIONS[i],
63 bind(std::plus<int>(), 0, 0)); // no-op.
64 }
65 }
Alexander Afanasyev3ecec502014-04-16 13:42:44 -070066
67 // parse config file
68 config.parse(configFile, true);
69 config.parse(configFile, false);
70
71 m_ribManager->registerWithNfd();
72 m_ribManager->enableLocalControlHeader();
73 }
74
75 void
76 initializeLogging(const std::string& configFile)
77 {
78 ConfigFile config;
79 LoggerFactory::getInstance().setConfigFile(config);
80
81 for (size_t i = 0; i < N_SUPPORTED_CONFIG_SECTIONS; ++i)
82 {
83 if (SUPPORTED_CONFIG_SECTIONS[i] != "log")
84 {
85 config.addSectionHandler(SUPPORTED_CONFIG_SECTIONS[i],
86 bind(std::plus<int>(), 0, 0)); // no-op.
87 }
88 }
89
90 config.parse(configFile, true);
91 config.parse(configFile, false);
92 }
93
94 boost::asio::io_service&
95 getIoService()
96 {
97 return m_ribManager->getIoService();
98 }
99
100 static void
101 printUsage(std::ostream& os, const std::string& programName)
102 {
103 os << "Usage: \n"
104 << " " << programName << " [options]\n"
105 << "\n"
106 << "Run NRD daemon\n"
107 << "\n"
108 << "Options:\n"
109 << " [--help] - print this help message\n"
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700110 << " [--config /path/to/nfd.conf] - path to configuration file "
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700111 << "(default: " << DEFAULT_CONFIG_FILE << ")\n"
112 ;
113 }
114
115 static void
116 printModules(std::ostream& os)
117 {
118 using namespace std;
119
120 os << "Available logging modules: \n";
121
122 list<string> modules(LoggerFactory::getInstance().getModules());
123 for (list<string>::const_iterator i = modules.begin(); i != modules.end(); ++i)
124 {
125 os << *i << "\n";
126 }
127 }
128
129 static bool
130 parseCommandLine(int argc, char** argv, ProgramOptions& options)
131 {
132 options.showUsage = false;
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700133 options.showModules = false;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700134 options.config = DEFAULT_CONFIG_FILE;
135
136 while (true) {
137 int optionIndex = 0;
138 static ::option longOptions[] = {
139 { "help" , no_argument , 0, 0 },
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700140 { "modules", no_argument , 0, 0 },
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700141 { "config" , required_argument, 0, 0 },
142 { 0 , 0 , 0, 0 }
143 };
144 int c = getopt_long_only(argc, argv, "", longOptions, &optionIndex);
145 if (c == -1)
146 break;
147
148 switch (c) {
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700149 case 0:
150 switch (optionIndex) {
151 case 0: // help
152 options.showUsage = true;
153 break;
154 case 1: // modules
155 options.showModules = true;
156 break;
157 case 2: // config
158 options.config = ::optarg;
159 break;
160 default:
161 return false;
162 }
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700163 break;
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700164 }
165 }
166 return true;
167 }
168
169
170 void
171 terminate(const boost::system::error_code& error,
172 int signalNo,
173 boost::asio::signal_set& signalSet)
174 {
175 if (error)
176 return;
177
178 if (signalNo == SIGINT ||
179 signalNo == SIGTERM)
180 {
181 getIoService().stop();
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700182 NFD_LOG_INFO("Caught signal '" << strsignal(signalNo) << "', exiting...");
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700183 }
184 else
185 {
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700186 /// \todo May be try to reload config file
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700187 signalSet.async_wait(bind(&Nrd::terminate, this, _1, _2,
188 boost::ref(signalSet)));
189 }
190 }
191
192private:
193 shared_ptr<RibManager> m_ribManager;
194
195 static const std::string SUPPORTED_CONFIG_SECTIONS[];
196 static const size_t N_SUPPORTED_CONFIG_SECTIONS;
197};
198
199const std::string Nrd::SUPPORTED_CONFIG_SECTIONS[] =
200 {
201 "log",
Alexander Afanasyev89cf5e02014-04-17 12:08:57 -0700202 "face_system",
203 "authorizations",
204 "rib_security",
Alexander Afanasyev3ecec502014-04-16 13:42:44 -0700205 };
206
207const size_t Nrd::N_SUPPORTED_CONFIG_SECTIONS =
208 sizeof(SUPPORTED_CONFIG_SECTIONS) / sizeof(std::string);
209
210} // namespace rib
211} // namespace nfd
212
213int
214main(int argc, char** argv)
215{
216 using namespace nfd::rib;
217
218 ProgramOptions options;
219 bool isCommandLineValid = Nrd::parseCommandLine(argc, argv, options);
220 if (!isCommandLineValid) {
221 Nrd::printUsage(std::cerr, argv[0]);
222 return 1;
223 }
224 if (options.showUsage) {
225 Nrd::printUsage(std::cout, argv[0]);
226 return 0;
227 }
228
229 if (options.showModules) {
230 Nrd::printModules(std::cout);
231 return 0;
232 }
233
234 Nrd nrdInstance;
235
236 try {
237 nrdInstance.initialize(options.config);
238 }
239 catch (boost::filesystem::filesystem_error& e) {
240 if (e.code() == boost::system::errc::permission_denied) {
241 NFD_LOG_FATAL("Permissions denied for " << e.path1() << ". " <<
242 argv[0] << " should be run as superuser");
243 }
244 else {
245 NFD_LOG_FATAL(e.what());
246 }
247 return 1;
248 }
249 catch (const std::exception& e) {
250 NFD_LOG_FATAL(e.what());
251 return 2;
252 }
253
254 boost::asio::signal_set signalSet(nrdInstance.getIoService());
255 signalSet.add(SIGINT);
256 signalSet.add(SIGTERM);
257 signalSet.add(SIGHUP);
258 signalSet.add(SIGUSR1);
259 signalSet.add(SIGUSR2);
260 signalSet.async_wait(bind(&Nrd::terminate, &nrdInstance, _1, _2,
261 boost::ref(signalSet)));
262
263 try {
264 nrdInstance.getIoService().run();
265 }
266 catch (std::exception& e) {
267 NFD_LOG_FATAL(e.what());
268 return 3;
269 }
270
271 return 0;
272}