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