blob: fad493347873185f25eec49117169a5e63f048bd [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/*
Junxiao Shi83be1da2017-06-30 13:37:37 +00003 * Copyright (c) 2014-2017, 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"
27#include "core/extended-error-message.hpp"
28#include "core/scheduler.hpp"
Junxiao Shi9f5b01d2016-08-05 03:54:28 +000029#include "core/version.hpp"
Alexander Afanasyev2a655f72015-01-26 18:38:33 -080030
Junxiao Shicb766862017-07-07 22:21:04 +000031#include <signal.h>
32#include <string.h>
Alexander Afanasyev5c475972015-12-20 16:16:56 -080033#include <boost/program_options/options_description.hpp>
Alexander Afanasyev5c475972015-12-20 16:16:56 -080034#include <boost/program_options/parsers.hpp>
Junxiao Shi52fa45c2016-11-29 21:18:13 +000035#include <boost/program_options/variables_map.hpp>
Junxiao Shicb766862017-07-07 22:21:04 +000036#include <ndn-cxx/net/network-monitor.hpp>
37#include <ndn-cxx/util/scheduler.hpp>
38#include <ndn-cxx/util/scheduler-scoped-event-id.hpp>
39#include <ndn-cxx/util/time.hpp>
Alexander Afanasyev2a655f72015-01-26 18:38:33 -080040
41namespace ndn {
42namespace tools {
Junxiao Shi52fa45c2016-11-29 21:18:13 +000043namespace autoconfig {
44// ndn-autoconfig is an NDN tool not an NFD tool, so it uses ndn::tools::autoconfig namespace.
45// It lives in NFD repository because nfd-start can automatically start ndn-autoconfig in daemon mode.
Alexander Afanasyev2a655f72015-01-26 18:38:33 -080046
Junxiao Shicb766862017-07-07 22:21:04 +000047static const time::nanoseconds DAEMON_INITIAL_DELAY = time::milliseconds(100);
48static const time::nanoseconds DAEMON_UNCONDITIONAL_INTERVAL = time::hours(1);
49static const time::nanoseconds NETMON_DAMPEN_PERIOD = time::seconds(5);
50
51namespace po = boost::program_options;
52
53static void
54usage(std::ostream& os,
55 const po::options_description& optionsDescription,
56 const char* programName)
Alexander Afanasyev2a655f72015-01-26 18:38:33 -080057{
Junxiao Shicb766862017-07-07 22:21:04 +000058 os << "Usage:\n"
59 << " " << programName << " [options]\n"
60 << "\n";
61 os << optionsDescription;
62}
63
64static void
65runDaemon(Procedure& proc)
66{
67 boost::asio::signal_set terminateSignals(proc.getIoService());
68 terminateSignals.add(SIGINT);
69 terminateSignals.add(SIGTERM);
70 terminateSignals.async_wait([&] (const boost::system::error_code& error, int signalNo) {
71 if (error) {
72 return;
Alexander Afanasyev2a655f72015-01-26 18:38:33 -080073 }
Junxiao Shicb766862017-07-07 22:21:04 +000074 const char* signalName = ::strsignal(signalNo);
75 std::cerr << "Exit on signal ";
76 if (signalName == nullptr) {
77 std::cerr << signalNo;
78 }
79 else {
80 std::cerr << signalName;
81 }
82 std::cerr << std::endl;
83 proc.getIoService().stop();
84 });
85
86 util::Scheduler sched(proc.getIoService());
87 util::scheduler::ScopedEventId runEvt(sched);
88 auto scheduleRerun = [&] (time::nanoseconds delay) {
89 runEvt = sched.scheduleEvent(delay, [&] { proc.runOnce(); });
Alexander Afanasyev2a655f72015-01-26 18:38:33 -080090 };
91
Junxiao Shicb766862017-07-07 22:21:04 +000092 proc.onComplete.connect([&] (bool isSuccess) {
93 scheduleRerun(DAEMON_UNCONDITIONAL_INTERVAL);
94 });
Alexander Afanasyeve46279dc2015-01-29 15:39:17 -080095
Junxiao Shicb766862017-07-07 22:21:04 +000096 net::NetworkMonitor netmon(proc.getIoService());
97 netmon.onNetworkStateChanged.connect([&] { scheduleRerun(NETMON_DAMPEN_PERIOD); });
Alexander Afanasyev2a655f72015-01-26 18:38:33 -080098
Junxiao Shicb766862017-07-07 22:21:04 +000099 scheduleRerun(DAEMON_INITIAL_DELAY);
100 proc.getIoService().run();
101}
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800102
Junxiao Shi52fa45c2016-11-29 21:18:13 +0000103static int
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800104main(int argc, char** argv)
105{
Junxiao Shicb766862017-07-07 22:21:04 +0000106 Options options;
107 bool isDaemon = false;
Alexander Afanasyev5c475972015-12-20 16:16:56 -0800108 std::string configFile;
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800109
Junxiao Shicb766862017-07-07 22:21:04 +0000110 po::options_description optionsDescription("Options");
111 optionsDescription.add_options()
112 ("help,h", "print this message and exit")
113 ("version,V", "display version and exit")
114 ("daemon,d", po::bool_switch(&isDaemon)->default_value(isDaemon),
115 "run in daemon mode, detecting network change events and re-running auto-discovery procedure. "
116 "In addition, the auto-discovery procedure is unconditionally re-run every hour.\n"
Alexander Afanasyev5c475972015-12-20 16:16:56 -0800117 "NOTE: if connection to NFD fails, the daemon will be terminated.")
Junxiao Shicb766862017-07-07 22:21:04 +0000118 ("ndn-fch-url", po::value<std::string>(&options.ndnFchUrl)->default_value(options.ndnFchUrl),
Alexander Afanasyev2a001942016-12-14 18:18:41 -0800119 "URL for NDN-FCH (Find Closest Hub) service")
Junxiao Shicb766862017-07-07 22:21:04 +0000120 ("config,c", po::value<std::string>(&configFile),
121 "configuration file. Exit immediately if `enabled = true` is not specified in config file.")
Alexander Afanasyev5c475972015-12-20 16:16:56 -0800122 ;
123
Junxiao Shicb766862017-07-07 22:21:04 +0000124 po::variables_map vm;
Alexander Afanasyev5c475972015-12-20 16:16:56 -0800125 try {
Junxiao Shicb766862017-07-07 22:21:04 +0000126 po::store(po::parse_command_line(argc, argv, optionsDescription), vm);
127 po::notify(vm);
Alexander Afanasyev5c475972015-12-20 16:16:56 -0800128 }
129 catch (const std::exception& e) {
Junxiao Shicb766862017-07-07 22:21:04 +0000130 std::cerr << "ERROR: " << e.what() << "\n" << "\n\n";
131 usage(std::cerr, optionsDescription, argv[0]);
132 return 2;
Alexander Afanasyev5c475972015-12-20 16:16:56 -0800133 }
134
Junxiao Shicb766862017-07-07 22:21:04 +0000135 if (vm.count("help")) {
136 usage(std::cout, optionsDescription, argv[0]);
Alexander Afanasyev5c475972015-12-20 16:16:56 -0800137 return 0;
138 }
139
Junxiao Shicb766862017-07-07 22:21:04 +0000140 if (vm.count("version")) {
Alexander Afanasyev5c475972015-12-20 16:16:56 -0800141 std::cout << NFD_VERSION_BUILD_STRING << std::endl;
142 return 0;
143 }
144
Junxiao Shicb766862017-07-07 22:21:04 +0000145 if (vm.count("config")) {
146 po::options_description configFileOptions;
147 configFileOptions.add_options()
148 ("enabled", po::value<bool>()->default_value(false))
149 ;
Alexander Afanasyev5c475972015-12-20 16:16:56 -0800150 try {
Junxiao Shicb766862017-07-07 22:21:04 +0000151 po::store(po::parse_config_file<char>(configFile.data(), configFileOptions), vm);
152 po::notify(vm);
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800153 }
Alexander Afanasyev5c475972015-12-20 16:16:56 -0800154 catch (const std::exception& e) {
Junxiao Shicb766862017-07-07 22:21:04 +0000155 std::cerr << "ERROR in config: " << e.what() << "\n\n";
156 return 2;
157 }
158 if (!vm["enabled"].as<bool>()) {
159 // not enabled in config
160 return 0;
Alexander Afanasyev5c475972015-12-20 16:16:56 -0800161 }
162 }
163
Junxiao Shicb766862017-07-07 22:21:04 +0000164 int exitCode = 0;
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800165 try {
Junxiao Shicb766862017-07-07 22:21:04 +0000166 Face face;
167 KeyChain keyChain;
168 Procedure proc(face, keyChain);
169 proc.initialize(options);
170
171 if (isDaemon) {
172 runDaemon(proc);
173 }
174 else {
175 proc.onComplete.connect([&exitCode] (bool isSuccess) { exitCode = isSuccess ? 0 : 3; });
176 proc.runOnce();
177 face.processEvents();
178 }
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800179 }
Junxiao Shicb766862017-07-07 22:21:04 +0000180 catch (const std::exception& e) {
181 std::cerr << ::nfd::getExtendedErrorMessage(e) << std::endl;
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800182 return 1;
183 }
Junxiao Shicb766862017-07-07 22:21:04 +0000184 return exitCode;
Alexander Afanasyev2a655f72015-01-26 18:38:33 -0800185}
Junxiao Shi52fa45c2016-11-29 21:18:13 +0000186
187} // namespace autoconfig
188} // namespace tools
189} // namespace ndn
190
191int
192main(int argc, char** argv)
193{
194 return ndn::tools::autoconfig::main(argc, argv);
195}