36 #include <boost/asio/signal_set.hpp>
37 #include <boost/config.hpp>
38 #include <boost/exception/diagnostic_information.hpp>
39 #include <boost/program_options/options_description.hpp>
40 #include <boost/program_options/parsers.hpp>
41 #include <boost/program_options/variables_map.hpp>
42 #include <boost/system/system_error.hpp>
43 #include <boost/version.hpp>
46 #include <condition_variable>
48 #include <system_error>
51 #include <ndn-cxx/util/logging.hpp>
52 #include <ndn-cxx/util/ostream-joiner.hpp>
53 #include <ndn-cxx/version.hpp>
55 #ifdef NFD_HAVE_LIBPCAP
56 #include <pcap/pcap.h>
58 #ifdef NFD_HAVE_SYSTEMD
59 #include <systemd/sd-daemon.h>
61 #ifdef NFD_HAVE_WEBSOCKET
62 #include <websocketpp/version.hpp>
65 namespace po = boost::program_options;
80 class NfdRunner : noncopyable
84 NfdRunner(
const std::string& configFile)
85 : m_nfd(configFile, m_nfdKeyChain)
86 , m_configFile(configFile)
90 m_terminateSignals.async_wait([
this] (
auto&&... args) {
91 terminate(std::forward<decltype(args)>(args)...);
93 m_reloadSignals.async_wait([
this] (
auto&&... args) {
94 reload(std::forward<decltype(args)>(args)...);
109 std::atomic_int retval(0);
113 boost::asio::io_context* ribIo =
nullptr;
120 std::condition_variable cv;
122 std::thread ribThread([configFile = m_configFile, &retval, &ribIo, mainIo, &cv, &m] {
124 std::lock_guard<std::mutex> lock(m);
126 BOOST_ASSERT(ribIo != mainIo);
132 ndn::KeyChain ribKeyChain;
134 rib::Service ribService(configFile, ribKeyChain);
137 catch (
const std::exception& e) {
144 std::lock_guard<std::mutex> lock(m);
152 std::unique_lock<std::mutex> lock(m);
153 cv.wait(lock, [&ribIo] {
return ribIo !=
nullptr; });
157 systemdNotify(
"READY=1");
160 catch (
const std::exception& e) {
164 catch (
const PrivilegeHelper::Error& e) {
171 std::lock_guard<std::mutex> lock(m);
172 if (ribIo !=
nullptr) {
183 systemdNotify(
const char* state)
185 #ifdef NFD_HAVE_SYSTEMD
192 terminate(
const boost::system::error_code& error,
int signalNo)
197 NFD_LOG_INFO(
"Caught signal " << signalNo <<
" (" << ::strsignal(signalNo) <<
"), exiting...");
199 systemdNotify(
"STOPPING=1");
204 reload(
const boost::system::error_code& error,
int signalNo)
209 NFD_LOG_INFO(
"Caught signal " << signalNo <<
" (" << ::strsignal(signalNo) <<
"), reloading...");
211 systemdNotify(
"RELOADING=1");
212 m_nfd.reloadConfigFile();
213 systemdNotify(
"READY=1");
215 m_reloadSignals.async_wait([
this] (
auto&&... args) {
216 reload(std::forward<decltype(args)>(args)...);
221 ndn::KeyChain m_nfdKeyChain;
223 std::string m_configFile;
225 boost::asio::signal_set m_terminateSignals;
226 boost::asio::signal_set m_reloadSignals;
230 printUsage(std::ostream& os,
const char* programName,
const po::options_description& opts)
232 os <<
"Usage: " << programName <<
" [options]\n"
234 <<
"Run the NDN Forwarding Daemon (NFD)\n"
242 const auto& modules = ndn::util::Logging::getLoggerNames();
243 std::copy(modules.begin(), modules.end(), ndn::make_ostream_joiner(os,
"\n"));
254 std::string configFile = NFD_DEFAULT_CONFIG_FILE;
256 po::options_description description(
"Options");
257 description.add_options()
258 (
"help,h",
"print this message and exit")
259 (
"version,V",
"show version information and exit")
260 (
"config,c", po::value<std::string>(&configFile),
261 "path to configuration file (default: " NFD_DEFAULT_CONFIG_FILE
")")
262 (
"modules,m",
"list available logging modules")
265 po::variables_map vm;
267 po::store(po::parse_command_line(argc, argv, description), vm);
270 catch (
const std::exception& e) {
274 std::cerr <<
"ERROR: " << e.what() <<
"\n\n";
279 if (vm.count(
"help") > 0) {
284 if (vm.count(
"version") > 0) {
289 if (vm.count(
"modules") > 0) {
294 const std::string boostBuildInfo =
295 "with Boost version " + std::to_string(BOOST_VERSION / 100000) +
296 "." + std::to_string(BOOST_VERSION / 100 % 1000) +
297 "." + std::to_string(BOOST_VERSION % 100);
298 const std::string pcapBuildInfo =
299 #ifdef NFD_HAVE_LIBPCAP
300 "with " + std::string(pcap_lib_version());
304 const std::string wsBuildInfo =
305 #ifdef NFD_HAVE_WEBSOCKET
306 "with WebSocket++ version " + std::to_string(websocketpp::major_version) +
307 "." + std::to_string(websocketpp::minor_version) +
308 "." + std::to_string(websocketpp::patch_version);
310 "without WebSocket++";
314 <<
"Built with " BOOST_COMPILER
", with " BOOST_STDLIB
315 ", " << boostBuildInfo <<
316 ", " << pcapBuildInfo <<
317 ", " << wsBuildInfo <<
318 ", with ndn-cxx version " NDN_CXX_VERSION_BUILD_STRING
321 auto flush = ndn::make_scope_exit([] { ndn::util::Logging::flush(); });
323 NfdRunner runner(configFile);
327 catch (
const boost::system::system_error& e) {
329 if (e.code() == boost::system::errc::operation_not_permitted ||
330 e.code() == boost::system::errc::permission_denied) {
335 catch (
const std::system_error& e) {
337 if (e.code() == std::errc::operation_not_permitted ||
338 e.code() == std::errc::permission_denied) {
343 catch (
const std::exception& e) {
347 catch (
const PrivilegeHelper::Error& e) {
int main(int argc, char **argv)
#define NFD_LOG_INIT(name)
static void printUsage(std::ostream &os, const char *programName, const po::options_description &opts)
void setMainIoService(boost::asio::io_context *mainIo)
void setRibIoService(boost::asio::io_context *ribIo)
static void printLogModules(std::ostream &os)
boost::asio::io_context & getGlobalIoService()
Returns the global io_context instance for the calling thread.
const char NFD_VERSION_BUILD_STRING[]
NFD version string, including git commit information if NFD is build from a specific git commit.