tools: Daemon mode for ndn-autoconfig (re-run detection when connectivity changes)
Change-Id: I3cb870b13ba60d255162862c7dd0053ec5b578c4
Refs: #2417
diff --git a/tools/ndn-autoconfig/base-dns.cpp b/tools/ndn-autoconfig/base-dns.cpp
index 23e8782..60eed48 100644
--- a/tools/ndn-autoconfig/base-dns.cpp
+++ b/tools/ndn-autoconfig/base-dns.cpp
@@ -55,6 +55,12 @@
std::string srvDomain = "_ndn._udp." + fqdn;
std::cerr << "Sending DNS query for SRV record for " << srvDomain << std::endl;
+ res_init();
+
+ _res.retrans = 1;
+ _res.retry = 2;
+ _res.ndots = 10;
+
QueryAnswer queryAnswer;
int answerSize = res_query(srvDomain.c_str(),
ns_c_in,
@@ -77,6 +83,9 @@
QueryAnswer queryAnswer;
+ res_init();
+
+ _res.retrans = 1;
_res.retry = 2;
_res.ndots = 10;
diff --git a/tools/ndn-autoconfig/main.cpp b/tools/ndn-autoconfig/main.cpp
index d604c9d..01ac6a7 100644
--- a/tools/ndn-autoconfig/main.cpp
+++ b/tools/ndn-autoconfig/main.cpp
@@ -29,6 +29,10 @@
#include "guess-from-search-domains.hpp"
#include "guess-from-identity-name.hpp"
+#include <ndn-cxx/util/network-monitor.hpp>
+#include <ndn-cxx/util/scheduler.hpp>
+#include <ndn-cxx/util/scheduler-scoped-event-id.hpp>
+
#include <boost/noncopyable.hpp>
namespace ndn {
@@ -47,8 +51,14 @@
}
};
- NdnAutoconfig()
- : m_stage1(m_face, m_keyChain,
+ explicit
+ NdnAutoconfig(bool isDaemonMode)
+ : m_face(m_io)
+ , m_scheduler(m_io)
+ , m_startStagesEvent(m_scheduler)
+ , m_isDaemonMode(isDaemonMode)
+ , m_terminationSignalSet(m_io)
+ , m_stage1(m_face, m_keyChain,
[&] (const std::string& errorMessage) {
std::cerr << "Stage 1 failed: " << errorMessage << std::endl;
m_stage2.start();
@@ -61,16 +71,44 @@
, m_stage3(m_face, m_keyChain,
[&] (const std::string& errorMessage) {
std::cerr << "Stage 3 failed: " << errorMessage << std::endl;
- throw Error("No more stages, automatic discovery failed");
+ if (!m_isDaemonMode)
+ throw Error("No more stages, automatic discovery failed");
+ else
+ std::cerr << "No more stages, automatic discovery failed" << std::endl;
})
{
- m_stage1.start();
+ if (m_isDaemonMode) {
+ m_networkMonitor.reset(new util::NetworkMonitor(m_io));
+ m_networkMonitor->onNetworkStateChanged.connect([this] {
+ // delay stages, so if multiple events are triggered in short sequence,
+ // only one auto-detection procedure is triggered
+ m_startStagesEvent = m_scheduler.scheduleEvent(time::seconds(5),
+ bind(&NdnAutoconfig::startStages, this));
+ });
+ }
+
+ // Delay a little bit
+ m_startStagesEvent = m_scheduler.scheduleEvent(time::milliseconds(100),
+ bind(&NdnAutoconfig::startStages, this));
}
void
run()
{
- m_face.processEvents();
+ m_terminationSignalSet.add(SIGINT);
+ m_terminationSignalSet.add(SIGTERM);
+ m_terminationSignalSet.async_wait(bind(&NdnAutoconfig::terminate, this, _1, _2));
+
+ m_io.run();
+ }
+
+ void
+ terminate(const boost::system::error_code& error, int signalNo)
+ {
+ if (error)
+ return;
+
+ m_io.stop();
}
static void
@@ -81,13 +119,35 @@
<< "\n"
<< "Options:\n"
<< " [-h] - print usage and exit\n"
+ << " [-d] - run in daemon mode. In daemon mode, " << programName << " will try \n"
+ << " to detect network change events and re-run auto-discovery procedure.\n"
+ << " In addition, the auto-discovery procedure is unconditionally re-run\n"
+ << " every hour.\n"
+ << " NOTE: if connection to NFD fails, the daemon will be terminated.\n"
<< " [-V] - print version number and exit\n"
<< std::endl;
}
private:
+ void
+ startStages()
+ {
+ m_stage1.start();
+ if (m_isDaemonMode) {
+ m_startStagesEvent = m_scheduler.scheduleEvent(time::hours(1),
+ bind(&NdnAutoconfig::startStages, this));
+ }
+ }
+
+private:
+ boost::asio::io_service m_io;
Face m_face;
KeyChain m_keyChain;
+ unique_ptr<util::NetworkMonitor> m_networkMonitor;
+ util::Scheduler m_scheduler;
+ util::scheduler::ScopedEventId m_startStagesEvent;
+ bool m_isDaemonMode;
+ boost::asio::signal_set m_terminationSignalSet;
autoconfig::MulticastDiscovery m_stage1;
autoconfig::GuessFromSearchDomains m_stage2;
@@ -102,9 +162,13 @@
{
int opt;
const char* programName = argv[0];
+ bool isDaemonMode = false;
- while ((opt = getopt(argc, argv, "hV")) != -1) {
+ while ((opt = getopt(argc, argv, "dhV")) != -1) {
switch (opt) {
+ case 'd':
+ isDaemonMode = true;
+ break;
case 'h':
ndn::tools::NdnAutoconfig::usage(programName);
return 0;
@@ -115,7 +179,7 @@
}
try {
- ndn::tools::NdnAutoconfig autoConfigInstance;
+ ndn::tools::NdnAutoconfig autoConfigInstance(isDaemonMode);
autoConfigInstance.run();
}
catch (const std::exception& error) {