blob: 9602a9202e7fc5d3dce59e87398c74970dc247b3 [file] [log] [blame]
Alexander Afanasyev2a655f72015-01-26 18:38:33 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Junxiao Shicb766862017-07-07 22:21:04 +00002/*
Davide Pesaventoe277f8b2023-11-11 17:14:02 -05003 * Copyright (c) 2014-2023, Regents of the University of California,
Alexander Afanasyev2a655f72015-01-26 18:38:33 -08004 * 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
Junxiao Shicb766862017-07-07 22:21:04 +000026#include "procedure.hpp"
Junxiao Shi9f5b01d2016-08-05 03:54:28 +000027#include "core/version.hpp"
Alexander Afanasyev2a655f72015-01-26 18:38:33 -080028
Junxiao Shicb766862017-07-07 22:21:04 +000029#include <signal.h>
30#include <string.h>
Davide Pesavento97e33022019-02-14 16:00:50 -050031
Davide Pesaventoa9b09b62022-06-04 14:07:25 -040032#include <boost/asio/signal_set.hpp>
Davide Pesavento97e33022019-02-14 16:00:50 -050033#include <boost/exception/diagnostic_information.hpp>
Alexander Afanasyev5c475972015-12-20 16:16:56 -080034#include <boost/program_options/options_description.hpp>
Alexander Afanasyev5c475972015-12-20 16:16:56 -080035#include <boost/program_options/parsers.hpp>
Junxiao Shi52fa45c2016-11-29 21:18:13 +000036#include <boost/program_options/variables_map.hpp>
Davide Pesavento97e33022019-02-14 16:00:50 -050037
Junxiao Shicb766862017-07-07 22:21:04 +000038#include <ndn-cxx/net/network-monitor.hpp>
39#include <ndn-cxx/util/scheduler.hpp>
Junxiao Shicb766862017-07-07 22:21:04 +000040#include <ndn-cxx/util/time.hpp>
Alexander Afanasyev2a655f72015-01-26 18:38:33 -080041
Davide Pesaventoe422f9e2022-06-03 01:30:23 -040042namespace ndn::autoconfig {
Alexander Afanasyev2a655f72015-01-26 18:38:33 -080043
Junxiao Shicb766862017-07-07 22:21:04 +000044namespace po = boost::program_options;
45
Davide Pesaventoa3a7a4e2022-05-29 16:06:22 -040046constexpr time::nanoseconds DAEMON_INITIAL_DELAY = 100_ms;
47constexpr time::nanoseconds DAEMON_UNCONDITIONAL_INTERVAL = 1_h;
48constexpr time::nanoseconds NETMON_DAMPEN_PERIOD = 5_s;
Davide Pesavento14e71f02019-03-28 17:35:25 -040049
Junxiao Shicb766862017-07-07 22:21:04 +000050static void
51usage(std::ostream& os,
Davide Pesavento59769b12017-11-12 23:52:06 -050052 const po::options_description& opts,
Junxiao Shicb766862017-07-07 22:21:04 +000053 const char* programName)
Alexander Afanasyev2a655f72015-01-26 18:38:33 -080054{
Davide Pesavento59769b12017-11-12 23:52:06 -050055 os << "Usage: " << programName << " [options]\n"
56 << "\n"
57 << opts;
Junxiao Shicb766862017-07-07 22:21:04 +000058}
59
60static void
61runDaemon(Procedure& proc)
62{
Davide Pesaventoe277f8b2023-11-11 17:14:02 -050063 boost::asio::signal_set terminateSignals(proc.getIoContext());
Junxiao Shicb766862017-07-07 22:21:04 +000064 terminateSignals.add(SIGINT);
65 terminateSignals.add(SIGTERM);
Davide Pesaventoe277f8b2023-11-11 17:14:02 -050066 terminateSignals.async_wait([&] (const auto& error, int signalNo) {
Junxiao Shicb766862017-07-07 22:21:04 +000067 if (error) {
68 return;
Alexander Afanasyev2a655f72015-01-26 18:38:33 -080069 }
Junxiao Shicb766862017-07-07 22:21:04 +000070 const char* signalName = ::strsignal(signalNo);
Davide Pesavento59769b12017-11-12 23:52:06 -050071 std::cerr << "Exiting on signal ";
Junxiao Shicb766862017-07-07 22:21:04 +000072 if (signalName == nullptr) {
73 std::cerr << signalNo;
74 }
75 else {
76 std::cerr << signalName;
77 }
78 std::cerr << std::endl;
Davide Pesaventoe277f8b2023-11-11 17:14:02 -050079 proc.getIoContext().stop();
Junxiao Shicb766862017-07-07 22:21:04 +000080 });
81
Davide Pesaventoe277f8b2023-11-11 17:14:02 -050082 Scheduler sched(proc.getIoContext());
Davide Pesavento3dade002019-03-19 11:29:56 -060083 scheduler::ScopedEventId runEvt;
Junxiao Shicb766862017-07-07 22:21:04 +000084 auto scheduleRerun = [&] (time::nanoseconds delay) {
Davide Pesavento3dade002019-03-19 11:29:56 -060085 runEvt = sched.schedule(delay, [&] { proc.runOnce(); });
Alexander Afanasyev2a655f72015-01-26 18:38:33 -080086 };
87
Junxiao Shicb766862017-07-07 22:21:04 +000088 proc.onComplete.connect([&] (bool isSuccess) {
89 scheduleRerun(DAEMON_UNCONDITIONAL_INTERVAL);
90 });
Alexander Afanasyeve46279dc2015-01-29 15:39:17 -080091
Davide Pesaventoe277f8b2023-11-11 17:14:02 -050092 net::NetworkMonitor netmon(proc.getIoContext());
Junxiao Shicb766862017-07-07 22:21:04 +000093 netmon.onNetworkStateChanged.connect([&] { scheduleRerun(NETMON_DAMPEN_PERIOD); });
Alexander Afanasyev2a655f72015-01-26 18:38:33 -080094
Junxiao Shicb766862017-07-07 22:21:04 +000095 scheduleRerun(DAEMON_INITIAL_DELAY);
Davide Pesaventoe277f8b2023-11-11 17:14:02 -050096 proc.getIoContext().run();
Junxiao Shicb766862017-07-07 22:21:04 +000097}
Alexander Afanasyev2a655f72015-01-26 18:38:33 -080098
Junxiao Shi52fa45c2016-11-29 21:18:13 +000099static int
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800100main(int argc, char** argv)
101{
Junxiao Shicb766862017-07-07 22:21:04 +0000102 Options options;
103 bool isDaemon = false;
Alexander Afanasyev5c475972015-12-20 16:16:56 -0800104 std::string configFile;
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800105
Junxiao Shicb766862017-07-07 22:21:04 +0000106 po::options_description optionsDescription("Options");
107 optionsDescription.add_options()
108 ("help,h", "print this message and exit")
Davide Pesavento59769b12017-11-12 23:52:06 -0500109 ("version,V", "show version information and exit")
Junxiao Shicb766862017-07-07 22:21:04 +0000110 ("daemon,d", po::bool_switch(&isDaemon)->default_value(isDaemon),
Davide Pesavento59769b12017-11-12 23:52:06 -0500111 "Run in daemon mode, detecting network change events and re-running the auto-discovery procedure. "
Junxiao Shicb766862017-07-07 22:21:04 +0000112 "In addition, the auto-discovery procedure is unconditionally re-run every hour.\n"
Davide Pesavento59769b12017-11-12 23:52:06 -0500113 "NOTE: if the connection to NFD fails, the daemon will exit.")
Junxiao Shicb766862017-07-07 22:21:04 +0000114 ("ndn-fch-url", po::value<std::string>(&options.ndnFchUrl)->default_value(options.ndnFchUrl),
Alexander Afanasyev2a001942016-12-14 18:18:41 -0800115 "URL for NDN-FCH (Find Closest Hub) service")
Junxiao Shicb766862017-07-07 22:21:04 +0000116 ("config,c", po::value<std::string>(&configFile),
Davide Pesavento59769b12017-11-12 23:52:06 -0500117 "Configuration file. Exit immediately unless 'enabled = true' is specified in the config file.")
Alexander Afanasyev5c475972015-12-20 16:16:56 -0800118 ;
119
Junxiao Shicb766862017-07-07 22:21:04 +0000120 po::variables_map vm;
Alexander Afanasyev5c475972015-12-20 16:16:56 -0800121 try {
Junxiao Shicb766862017-07-07 22:21:04 +0000122 po::store(po::parse_command_line(argc, argv, optionsDescription), vm);
123 po::notify(vm);
Alexander Afanasyev5c475972015-12-20 16:16:56 -0800124 }
125 catch (const std::exception& e) {
Davide Pesavento59769b12017-11-12 23:52:06 -0500126 std::cerr << "ERROR: " << e.what() << "\n\n";
Junxiao Shicb766862017-07-07 22:21:04 +0000127 usage(std::cerr, optionsDescription, argv[0]);
128 return 2;
Alexander Afanasyev5c475972015-12-20 16:16:56 -0800129 }
130
Junxiao Shicb766862017-07-07 22:21:04 +0000131 if (vm.count("help")) {
132 usage(std::cout, optionsDescription, argv[0]);
Alexander Afanasyev5c475972015-12-20 16:16:56 -0800133 return 0;
134 }
135
Junxiao Shicb766862017-07-07 22:21:04 +0000136 if (vm.count("version")) {
Alexander Afanasyev5c475972015-12-20 16:16:56 -0800137 std::cout << NFD_VERSION_BUILD_STRING << std::endl;
138 return 0;
139 }
140
Junxiao Shicb766862017-07-07 22:21:04 +0000141 if (vm.count("config")) {
142 po::options_description configFileOptions;
143 configFileOptions.add_options()
144 ("enabled", po::value<bool>()->default_value(false))
145 ;
Alexander Afanasyev5c475972015-12-20 16:16:56 -0800146 try {
Junxiao Shicb766862017-07-07 22:21:04 +0000147 po::store(po::parse_config_file<char>(configFile.data(), configFileOptions), vm);
148 po::notify(vm);
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800149 }
Alexander Afanasyev5c475972015-12-20 16:16:56 -0800150 catch (const std::exception& e) {
Junxiao Shicb766862017-07-07 22:21:04 +0000151 std::cerr << "ERROR in config: " << e.what() << "\n\n";
152 return 2;
153 }
154 if (!vm["enabled"].as<bool>()) {
155 // not enabled in config
156 return 0;
Alexander Afanasyev5c475972015-12-20 16:16:56 -0800157 }
158 }
159
Junxiao Shicb766862017-07-07 22:21:04 +0000160 int exitCode = 0;
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800161 try {
Junxiao Shicb766862017-07-07 22:21:04 +0000162 Face face;
163 KeyChain keyChain;
164 Procedure proc(face, keyChain);
165 proc.initialize(options);
166
167 if (isDaemon) {
168 runDaemon(proc);
169 }
170 else {
Davide Pesavento59769b12017-11-12 23:52:06 -0500171 proc.onComplete.connect([&exitCode] (bool isSuccess) { exitCode = isSuccess ? 0 : 1; });
Junxiao Shicb766862017-07-07 22:21:04 +0000172 proc.runOnce();
173 face.processEvents();
174 }
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800175 }
Junxiao Shicb766862017-07-07 22:21:04 +0000176 catch (const std::exception& e) {
Davide Pesavento97e33022019-02-14 16:00:50 -0500177 std::cerr << "ERROR: " << boost::diagnostic_information(e);
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800178 return 1;
179 }
Davide Pesavento59769b12017-11-12 23:52:06 -0500180
Junxiao Shicb766862017-07-07 22:21:04 +0000181 return exitCode;
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800182}
Junxiao Shi52fa45c2016-11-29 21:18:13 +0000183
Davide Pesaventoe422f9e2022-06-03 01:30:23 -0400184} // namespace ndn::autoconfig
Junxiao Shi52fa45c2016-11-29 21:18:13 +0000185
186int
187main(int argc, char** argv)
188{
Davide Pesaventoe422f9e2022-06-03 01:30:23 -0400189 return ndn::autoconfig::main(argc, argv);
Junxiao Shi52fa45c2016-11-29 21:18:13 +0000190}