nrd-config: Adding processing of command line arguments and processing of conf file.
refs #1450
Change-Id: I18fa5c1c12ec2367670659be331a9f95e0a920eb
diff --git a/src/common.hpp b/src/common.hpp
index 650f2de..f520828 100644
--- a/src/common.hpp
+++ b/src/common.hpp
@@ -22,5 +22,24 @@
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/regex_find_format.hpp>
+#include <boost/property_tree/ptree.hpp>
+#include <boost/property_tree/info_parser.hpp>
+#include "../build/src/config.hpp"
+
+namespace ndn {
+namespace nrd {
+
+class Error : public std::runtime_error
+{
+public:
+ explicit
+ Error(const std::string& what)
+ : std::runtime_error(what)
+ {
+ }
+};
+
+} //namespace nrd
+} //namespace ndn
#endif // NRD_COMMON_HPP
diff --git a/src/main.cpp b/src/main.cpp
index e360e5d..5d0e5ed 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -4,21 +4,97 @@
* See COPYING for copyright and distribution information.
*/
+#include "common.hpp"
#include "nrd.hpp"
+#include "nrd-config.hpp"
+#include <getopt.h>
+
+struct ProgramOptions
+{
+ bool showUsage;
+ std::string config;
+};
+
+static void
+printUsage(std::ostream& os, const std::string& programName)
+{
+ os << "Usage: \n"
+ << " " << programName << " [options]\n"
+ << "\n"
+ << "Run NRD daemon\n"
+ << "\n"
+ << "Options:\n"
+ << " [--help] - print this help message\n"
+ << " [--config /path/to/nrd.conf] - path to configuration file "
+ << "(default: " << DEFAULT_CONFIG_FILE << ")\n"
+ ;
+}
+
+static bool
+parseCommandLine(int argc, char** argv, ProgramOptions& options)
+{
+ options.showUsage = false;
+ options.config = DEFAULT_CONFIG_FILE;
+
+ while (true) {
+ int optionIndex = 0;
+ static ::option longOptions[] = {
+ { "help" , no_argument , 0, 0 },
+ { "config" , required_argument, 0, 0 },
+ { 0 , 0 , 0, 0 }
+ };
+ int c = getopt_long_only(argc, argv, "", longOptions, &optionIndex);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 0:
+ switch (optionIndex) {
+ case 0: // help
+ options.showUsage = true;
+ break;
+ case 1: // config
+ options.config = ::optarg;
+ break;
+ default:
+ return false;
+ }
+ break;
+ }
+ }
+ return true;
+}
int
main(int argc, char** argv)
{
- try {
- // TODO: the configFilename should be obtained from command line arguments.
- std::string configFilename("nrd.conf");
+ //processing command line arguments, if available
+ ProgramOptions options;
+ bool isCommandLineValid = parseCommandLine(argc, argv, options);
+ if (!isCommandLineValid) {
+ printUsage(std::cerr, argv[0]);
+ return 1;
+ }
+ if (options.showUsage) {
+ printUsage(std::cout, argv[0]);
+ return 0;
+ }
- ndn::nrd::Nrd nrd(configFilename);
+ //Now read the config file and pass the security section to validator
+ try {
+ std::string configFilename(options.config);
+
+ ndn::nrd::NrdConfig config;
+ config.load(configFilename);
+ ndn::nrd::ConfigSection securitySection = config.getSecuritySection();
+
+ ndn::nrd::Nrd nrd(securitySection, configFilename);
nrd.enableLocalControlHeader();
nrd.listen();
}
catch (std::exception& e) {
std::cerr << "ERROR: " << e.what() << std::endl;
}
+
return 0;
}
diff --git a/src/nrd-config.cpp b/src/nrd-config.cpp
new file mode 100644
index 0000000..c6181f9
--- /dev/null
+++ b/src/nrd-config.cpp
@@ -0,0 +1,116 @@
+#include "nrd-config.hpp"
+
+namespace ndn {
+namespace nrd {
+
+NrdConfig::NrdConfig()
+ : m_isSecuritySectionDefined(false)
+{
+}
+
+void
+NrdConfig::load(const std::string& filename)
+{
+ std::ifstream inputFile;
+ inputFile.open(filename.c_str());
+ if (!inputFile.good() || !inputFile.is_open())
+ {
+ std::string msg = "Failed to read configuration file: ";
+ msg += filename;
+ std::cerr << filename << std::endl;
+ throw Error(msg);
+ }
+ load(inputFile, filename);
+ inputFile.close();
+}
+
+void
+NrdConfig::load(const std::string& input, const std::string& filename)
+{
+ std::istringstream inputStream(input);
+ load(inputStream, filename);
+}
+
+void
+NrdConfig::load(std::istream& input, const std::string& filename)
+{
+ BOOST_ASSERT(!filename.empty());
+
+ ConfigSection ptree;
+ try
+ {
+ boost::property_tree::read_info(input, ptree);
+ }
+ catch (const boost::property_tree::info_parser_error& error)
+ {
+ std::stringstream msg;
+ msg << "Failed to parse configuration file";
+ msg << " " << filename;
+ msg << " " << error.message() << " line " << error.line();
+ throw Error(msg.str());
+ }
+ process(ptree, filename);
+}
+
+void
+NrdConfig::process(const ConfigSection& configSection,
+ const std::string& filename)
+{
+ BOOST_ASSERT(!filename.empty());
+
+ if (configSection.begin() == configSection.end())
+ {
+ std::string msg = "Error processing configuration file";
+ msg += ": ";
+ msg += filename;
+ msg += " no data";
+ throw Error(msg);
+ }
+
+ for (ConfigSection::const_iterator i = configSection.begin();
+ i != configSection.end(); ++i)
+ {
+ const std::string& sectionName = i->first;
+ const ConfigSection& section = i->second;
+
+ if (boost::iequals(sectionName, "security"))
+ {
+ onSectionSecurity(section, filename);
+ }
+ //Add more sections here as needed
+ //else if (boost::iequals(sectionName, "another-section"))
+ //{
+ //onSectionAnotherSection(section, filename);
+ //}
+ else
+ {
+ std::string msg = "Error processing configuration file";
+ msg += " ";
+ msg += filename;
+ msg += " unrecognized section: " + sectionName;
+ throw Error(msg);
+ }
+ }
+}
+
+void
+NrdConfig::onSectionSecurity(const ConfigSection& section,
+ const std::string& filename)
+{
+ if (!m_isSecuritySectionDefined) {
+ //setSecturitySection(section);
+ m_securitySection = section;
+ m_filename = filename;
+ m_isSecuritySectionDefined = true;
+ }
+ else {
+ std::string msg = "Error processing configuration file";
+ msg += " ";
+ msg += filename;
+ msg += " security section can appear only once";
+ throw Error(msg);
+ }
+}
+
+} //namespace nrd
+} //namespace ndn
diff --git a/src/nrd-config.hpp b/src/nrd-config.hpp
new file mode 100644
index 0000000..ee119f6
--- /dev/null
+++ b/src/nrd-config.hpp
@@ -0,0 +1,61 @@
+#ifndef NRD_CONFIG_HPP
+#define NRD_CONFIG_HPP
+
+#include "common.hpp"
+
+namespace ndn {
+namespace nrd {
+
+typedef boost::property_tree::ptree ConfigSection;
+
+class NrdConfig
+{
+
+public:
+ NrdConfig();
+
+ virtual
+ ~NrdConfig()
+ {
+ }
+
+ void
+ load(const std::string& filename);
+
+ void
+ load(const std::string& input, const std::string& filename);
+
+ void
+ load(std::istream& input, const std::string& filename);
+
+ const ConfigSection&
+ getSecuritySection() const
+ {
+ return m_securitySection;
+ }
+
+private:
+ void
+ process(const ConfigSection& configSection,
+ const std::string& filename);
+
+ void
+ onSectionSecurity(const ConfigSection& section,
+ const std::string& filename);
+
+ const void
+ setSecturitySection(const ConfigSection& securitySection)
+ {
+ m_securitySection = securitySection;
+ }
+
+private:
+ bool m_isSecuritySectionDefined;
+ ConfigSection m_securitySection;
+ std::string m_filename;
+};
+
+}//namespace nrd
+}//namespace ndn
+
+#endif // NRD_CONFIG_HPP
diff --git a/src/nrd.cpp b/src/nrd.cpp
index 09db6b2..492f9c2 100644
--- a/src/nrd.cpp
+++ b/src/nrd.cpp
@@ -34,7 +34,8 @@
),
};
-Nrd::Nrd(const std::string& validatorConfig)
+Nrd::Nrd(const ndn::nrd::ConfigSection& securitySection,
+ const std::string& validatorConfig)
: m_face(new Face())
, m_nfdController(new nfd::Controller(*m_face))
, m_validator(m_face)
@@ -45,7 +46,8 @@
//check whether the components of localhop and localhost prefixes are same
BOOST_ASSERT(COMMAND_PREFIX.size() == REMOTE_COMMAND_PREFIX.size());
- m_validator.load(validatorConfig);
+ //m_validator.load(validatorConfig);
+ m_validator.load(securitySection, validatorConfig);
std::cerr << "Setting interest filter on: " << COMMAND_PREFIX.toUri() << std::endl;
m_face->setController(m_nfdController);
@@ -70,7 +72,6 @@
m_face->shutdown();
}
-
void
Nrd::sendResponse(const Name& name,
const nfd::ControlResponse& response)
@@ -230,7 +231,6 @@
sendResponse(request.getName(), response);
}
-
void
Nrd::insertEntry(const Interest& request, const PrefixRegOptions& options)
{
@@ -248,7 +248,6 @@
bind(&Nrd::onCommandError, this, _1, _2, request, options));
}
-
void
Nrd::deleteEntry(const Interest& request, const PrefixRegOptions& options)
{
@@ -260,7 +259,6 @@
bind(&Nrd::onCommandError, this, _1, _2, request, options));
}
-
void
Nrd::listen()
{
@@ -268,14 +266,12 @@
m_face->processEvents();
}
-
void
Nrd::onControlHeaderSuccess()
{
std::cout << "Local control header enabled" << std::endl;
}
-
void
Nrd::onControlHeaderError(uint32_t code, const std::string& reason)
{
@@ -298,9 +294,10 @@
Nrd::onNotification(const nfd::FaceEventNotification& notification)
{
/// \todo A notification can be missed, in this case check Facelist
- if (notification.getKind() == 2) { //face destroyed
- m_managedRib.erase(notification.getFaceId());
- }
+ std::cerr << "Notification Rcvd: " << notification << std::endl;
+ if (notification.getKind() == ndn::nfd::FACE_EVENT_DESTROYED) { //face destroyed
+ m_managedRib.erase(notification.getFaceId());
+ }
}
} // namespace nrd
diff --git a/src/nrd.hpp b/src/nrd.hpp
index b441de8..d6007d7 100644
--- a/src/nrd.hpp
+++ b/src/nrd.hpp
@@ -9,15 +9,16 @@
#include "rib.hpp"
#include "face-monitor.hpp"
+#include "nrd-config.hpp"
namespace ndn {
namespace nrd {
-class Nrd
+class Nrd : noncopyable
{
public:
- explicit
- Nrd(const std::string& validatorConfig);
+ Nrd(const ndn::nrd::ConfigSection& securitySection,
+ const std::string& validatorConfig);
void
onRibRequest(const Interest& request);