Refactor config file parsing and improve error handling
Change-Id: I8a54ba1f0d414bea70923e0f45ca354ac7e957a3
diff --git a/src/ndn-traffic-client.cpp b/src/ndn-traffic-client.cpp
index adba253..005b8d4 100644
--- a/src/ndn-traffic-client.cpp
+++ b/src/ndn-traffic-client.cpp
@@ -18,7 +18,6 @@
* Author: Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
*/
-#include "logger.hpp"
#include "util.hpp"
#include <ndn-cxx/face.hpp>
@@ -27,7 +26,6 @@
#include <ndn-cxx/util/backports.hpp>
#include <ndn-cxx/util/random.hpp>
-#include <cctype>
#include <limits>
#include <vector>
@@ -36,7 +34,6 @@
#include <boost/asio/signal_set.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/lexical_cast.hpp>
-#include <boost/logic/tribool.hpp>
#include <boost/noncopyable.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/parsers.hpp>
@@ -58,12 +55,6 @@
{
}
- bool
- hasError() const
- {
- return m_hasError;
- }
-
void
setMaximumInterests(uint64_t maxInterests)
{
@@ -83,15 +74,30 @@
m_wantQuiet = true;
}
- void
+ int
run()
{
m_logger.initializeLog(to_string(random::generateWord32()));
- initializeTrafficConfiguration();
+
+ if (!readConfigurationFile(m_configurationFile, m_trafficPatterns, m_logger)) {
+ return 2;
+ }
+
+ if (!checkTrafficPatternCorrectness()) {
+ m_logger.log("ERROR: Traffic configuration provided is not proper", false, true);
+ return 2;
+ }
+
+ m_logger.log("Traffic configuration file processing completed.\n", true, false);
+ for (std::size_t i = 0; i < m_trafficPatterns.size(); i++) {
+ m_logger.log("Traffic Pattern Type #" + to_string(i + 1), false, false);
+ m_trafficPatterns[i].printTrafficConfiguration(m_logger);
+ m_logger.log("", false, false);
+ }
if (m_nMaximumInterests == 0) {
logStatistics();
- return;
+ return 0;
}
m_signalSet.async_wait([this] (auto&&...) { this->stop(); });
@@ -102,11 +108,12 @@
try {
m_face.processEvents();
+ return m_hasError ? 1 : 0;
}
catch (const std::exception& e) {
m_logger.log("ERROR: "s + e.what(), true, true);
- m_hasError = true;
m_ioService.stop();
+ return 1;
}
}
@@ -120,14 +127,12 @@
std::string detail;
detail += "TrafficPercentage=" + to_string(m_trafficPercentage) + ", ";
- if (!m_name.empty())
- detail += "Name=" + m_name + ", ";
+ detail += "Name=" + m_name + ", ";
if (m_nameAppendBytes)
detail += "NameAppendBytes=" + to_string(*m_nameAppendBytes) + ", ";
if (m_nameAppendSeqNum)
detail += "NameAppendSequenceNumber=" + to_string(*m_nameAppendSeqNum) + ", ";
- if (!boost::logic::indeterminate(m_mustBeFresh))
- detail += "MustBeFresh=" + to_string(bool(m_mustBeFresh)) + ", ";
+ detail += "MustBeFresh=" + to_string(m_mustBeFresh) + ", ";
if (m_nonceDuplicationPercentage > 0)
detail += "NonceDuplicationPercentage=" + to_string(m_nonceDuplicationPercentage) + ", ";
if (m_interestLifetime >= 0_ms)
@@ -143,36 +148,45 @@
}
bool
- processConfigurationDetail(const std::string& detail, Logger& logger, int lineNumber)
+ parseConfigurationLine(const std::string& line, Logger& logger, int lineNumber)
{
std::string parameter, value;
- if (parseParameterAndValue(detail, parameter, value)) {
- if (parameter == "TrafficPercentage")
- m_trafficPercentage = std::stoul(value);
- else if (parameter == "Name")
- m_name = value;
- else if (parameter == "NameAppendBytes")
- m_nameAppendBytes = std::stoul(value);
- else if (parameter == "NameAppendSequenceNumber")
- m_nameAppendSeqNum = std::stoull(value);
- else if (parameter == "MustBeFresh")
- m_mustBeFresh = bool(std::stoul(value));
- else if (parameter == "NonceDuplicationPercentage")
- m_nonceDuplicationPercentage = std::stoul(value);
- else if (parameter == "InterestLifetime")
- m_interestLifetime = time::milliseconds(std::stoul(value));
- else if (parameter == "NextHopFaceId")
- m_nextHopFaceId = std::stoull(value);
- else if (parameter == "ExpectedContent")
- m_expectedContent = value;
- else
- logger.log("Line " + to_string(lineNumber) +
- " - Unknown parameter '" + parameter + "'", false, true);
+ if (!extractParameterAndValue(line, parameter, value)) {
+ logger.log("Line " + to_string(lineNumber) + " - Invalid syntax: " + line,
+ false, true);
+ return false;
+ }
+
+ if (parameter == "TrafficPercentage") {
+ m_trafficPercentage = std::stoul(value);
+ }
+ else if (parameter == "Name") {
+ m_name = value;
+ }
+ else if (parameter == "NameAppendBytes") {
+ m_nameAppendBytes = std::stoul(value);
+ }
+ else if (parameter == "NameAppendSequenceNumber") {
+ m_nameAppendSeqNum = std::stoull(value);
+ }
+ else if (parameter == "MustBeFresh") {
+ m_mustBeFresh = parseBoolean(value);
+ }
+ else if (parameter == "NonceDuplicationPercentage") {
+ m_nonceDuplicationPercentage = std::stoul(value);
+ }
+ else if (parameter == "InterestLifetime") {
+ m_interestLifetime = time::milliseconds(std::stoul(value));
+ }
+ else if (parameter == "NextHopFaceId") {
+ m_nextHopFaceId = std::stoull(value);
+ }
+ else if (parameter == "ExpectedContent") {
+ m_expectedContent = value;
}
else {
- logger.log("Line " + to_string(lineNumber) +
- " - Invalid traffic configuration line: " + detail, false, true);
- return false;
+ logger.log("Line " + to_string(lineNumber) + " - Ignoring unknown parameter: " + parameter,
+ false, true);
}
return true;
}
@@ -188,7 +202,7 @@
std::string m_name;
optional<std::size_t> m_nameAppendBytes;
optional<uint64_t> m_nameAppendSeqNum;
- boost::logic::tribool m_mustBeFresh = boost::logic::indeterminate;
+ bool m_mustBeFresh = false;
uint8_t m_nonceDuplicationPercentage = 0;
time::milliseconds m_interestLifetime = -1_ms;
uint64_t m_nextHopFaceId = 0;
@@ -272,88 +286,10 @@
bool
checkTrafficPatternCorrectness() const
{
+ // TODO
return true;
}
- void
- parseConfigurationFile()
- {
- std::ifstream patternFile;
- m_logger.log("Parsing traffic configuration file: " + m_configurationFile, true, true);
-
- patternFile.open(m_configurationFile.data());
- if (patternFile.is_open()) {
- int lineNumber = 0;
- std::string patternLine;
- while (getline(patternFile, patternLine)) {
- lineNumber++;
- if (std::isalpha(patternLine[0])) {
- InterestTrafficConfiguration interestData;
- bool shouldSkipLine = false;
- if (interestData.processConfigurationDetail(patternLine, m_logger, lineNumber)) {
- while (getline(patternFile, patternLine) && std::isalpha(patternLine[0])) {
- lineNumber++;
- if (!interestData.processConfigurationDetail(patternLine, m_logger, lineNumber)) {
- shouldSkipLine = true;
- break;
- }
- }
- lineNumber++;
- }
- else {
- shouldSkipLine = true;
- }
- if (!shouldSkipLine) {
- if (interestData.checkTrafficDetailCorrectness()) {
- m_trafficPatterns.push_back(interestData);
- }
- }
- }
- }
- patternFile.close();
-
- if (!checkTrafficPatternCorrectness()) {
- m_logger.log("ERROR: Traffic configuration provided is not proper - " +
- m_configurationFile, false, true);
- exit(2);
- }
-
- m_logger.log("Traffic configuration file processing completed.\n", true, false);
- for (std::size_t patternId = 0; patternId < m_trafficPatterns.size(); patternId++) {
- m_logger.log("Traffic Pattern Type #" + to_string(patternId + 1), false, false);
- m_trafficPatterns[patternId].printTrafficConfiguration(m_logger);
- m_logger.log("", false, false);
- }
- }
- else {
- m_logger.log("ERROR: Unable to open traffic configuration file: " + m_configurationFile, false, true);
- exit(2);
- }
- }
-
- void
- initializeTrafficConfiguration()
- {
- namespace fs = boost::filesystem;
-
- fs::path configPath(m_configurationFile);
- if (fs::exists(configPath)) {
- if (fs::is_regular_file(configPath)) {
- parseConfigurationFile();
- }
- else {
- m_logger.log("ERROR: Traffic configuration file is not a regular file: " +
- m_configurationFile, false, true);
- exit(2);
- }
- }
- else {
- m_logger.log("ERROR: Traffic configuration file does not exist: " +
- m_configurationFile, false, true);
- exit(2);
- }
- }
-
uint32_t
getNewNonce()
{
@@ -409,10 +345,7 @@
}
interest.setName(name);
- if (pattern.m_mustBeFresh)
- interest.setMustBeFresh(true);
- else if (!pattern.m_mustBeFresh)
- interest.setMustBeFresh(false);
+ interest.setMustBeFresh(pattern.m_mustBeFresh);
static std::uniform_int_distribution<> duplicateNonceDist(1, 100);
if (duplicateNonceDist(random::getRandomNumberEngine()) <= pattern.m_nonceDuplicationPercentage)
@@ -688,7 +621,5 @@
client.setQuietLogging();
}
- client.run();
-
- return client.hasError() ? 1 : 0;
+ return client.run();
}
diff --git a/src/ndn-traffic-server.cpp b/src/ndn-traffic-server.cpp
index a6d8fef..25ace67 100644
--- a/src/ndn-traffic-server.cpp
+++ b/src/ndn-traffic-server.cpp
@@ -18,7 +18,6 @@
* Author: Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
*/
-#include "logger.hpp"
#include "util.hpp"
#include <ndn-cxx/data.hpp>
@@ -28,7 +27,6 @@
#include <ndn-cxx/util/backports.hpp>
#include <ndn-cxx/util/random.hpp>
-#include <cctype>
#include <limits>
#include <sstream>
#include <vector>
@@ -57,12 +55,6 @@
{
}
- bool
- hasError() const
- {
- return m_hasError;
- }
-
void
setMaximumInterests(uint64_t maxInterests)
{
@@ -82,15 +74,30 @@
m_wantQuiet = true;
}
- void
+ int
run()
{
m_logger.initializeLog(to_string(random::generateWord32()));
- initializeTrafficConfiguration();
+
+ if (!readConfigurationFile(m_configurationFile, m_trafficPatterns, m_logger)) {
+ return 2;
+ }
+
+ if (!checkTrafficPatternCorrectness()) {
+ m_logger.log("ERROR: Traffic configuration provided is not proper", false, true);
+ return 2;
+ }
+
+ m_logger.log("Traffic configuration file processing completed.\n", true, false);
+ for (std::size_t i = 0; i < m_trafficPatterns.size(); i++) {
+ m_logger.log("Traffic Pattern Type #" + to_string(i + 1), false, false);
+ m_trafficPatterns[i].printTrafficConfiguration(m_logger);
+ m_logger.log("", false, false);
+ }
if (m_nMaximumInterests == 0) {
logStatistics();
- return;
+ return 0;
}
m_signalSet.async_wait([this] (const boost::system::error_code&, int) {
@@ -110,11 +117,12 @@
try {
m_face.processEvents();
+ return m_hasError ? 1 : 0;
}
catch (const std::exception& e) {
m_logger.log("ERROR: "s + e.what(), true, true);
- m_hasError = true;
m_ioService.stop();
+ return 1;
}
}
@@ -151,40 +159,39 @@
}
bool
- processConfigurationDetail(const std::string& detail, Logger& logger, int lineNumber)
+ parseConfigurationLine(const std::string& line, Logger& logger, int lineNumber)
{
std::string parameter, value;
- if (parseParameterAndValue(detail, parameter, value)) {
- if (parameter == "Name") {
- m_name = value;
- }
- else if (parameter == "ContentDelay") {
- m_contentDelay = time::milliseconds(std::stoul(value));
- }
- else if (parameter == "FreshnessPeriod") {
- m_freshnessPeriod = time::milliseconds(std::stoul(value));
- }
- else if (parameter == "ContentType") {
- m_contentType = std::stoul(value);
- }
- else if (parameter == "ContentBytes") {
- m_contentLength = std::stoul(value);
- }
- else if (parameter == "Content") {
- m_content = value;
- }
- else if (parameter == "SigningInfo") {
- m_signingInfo = security::SigningInfo(value);
- }
- else {
- logger.log("Line " + to_string(lineNumber) +
- " - Unknown parameter '" + parameter + "'", false, true);
- }
+ if (!extractParameterAndValue(line, parameter, value)) {
+ logger.log("Line " + to_string(lineNumber) + " - Invalid syntax: " + line,
+ false, true);
+ return false;
+ }
+
+ if (parameter == "Name") {
+ m_name = value;
+ }
+ else if (parameter == "ContentDelay") {
+ m_contentDelay = time::milliseconds(std::stoul(value));
+ }
+ else if (parameter == "FreshnessPeriod") {
+ m_freshnessPeriod = time::milliseconds(std::stoul(value));
+ }
+ else if (parameter == "ContentType") {
+ m_contentType = std::stoul(value);
+ }
+ else if (parameter == "ContentBytes") {
+ m_contentLength = std::stoul(value);
+ }
+ else if (parameter == "Content") {
+ m_content = value;
+ }
+ else if (parameter == "SigningInfo") {
+ m_signingInfo = security::SigningInfo(value);
}
else {
- logger.log("Line " + to_string(lineNumber) +
- " - Invalid traffic configuration line: " + detail, false, true);
- return false;
+ logger.log("Line " + to_string(lineNumber) + " - Ignoring unknown parameter: " + parameter,
+ false, true);
}
return true;
}
@@ -226,88 +233,10 @@
bool
checkTrafficPatternCorrectness() const
{
+ // TODO
return true;
}
- void
- parseConfigurationFile()
- {
- std::ifstream patternFile;
- m_logger.log("Parsing traffic configuration file: " + m_configurationFile, true, true);
-
- patternFile.open(m_configurationFile.data());
- if (patternFile.is_open()) {
- int lineNumber = 0;
- std::string patternLine;
- while (getline(patternFile, patternLine)) {
- lineNumber++;
- if (std::isalpha(patternLine[0])) {
- DataTrafficConfiguration dataData;
- bool shouldSkipLine = false;
- if (dataData.processConfigurationDetail(patternLine, m_logger, lineNumber)) {
- while (getline(patternFile, patternLine) && std::isalpha(patternLine[0])) {
- lineNumber++;
- if (!dataData.processConfigurationDetail(patternLine, m_logger, lineNumber)) {
- shouldSkipLine = true;
- break;
- }
- }
- lineNumber++;
- }
- else {
- shouldSkipLine = true;
- }
- if (!shouldSkipLine) {
- if (dataData.checkTrafficDetailCorrectness()) {
- m_trafficPatterns.push_back(dataData);
- }
- }
- }
- }
- patternFile.close();
-
- if (!checkTrafficPatternCorrectness()) {
- m_logger.log("ERROR: Traffic configuration provided is not proper - " +
- m_configurationFile, false, true);
- exit(2);
- }
-
- m_logger.log("Traffic configuration file processing completed.\n", true, false);
- for (std::size_t patternId = 0; patternId < m_trafficPatterns.size(); patternId++) {
- m_logger.log("Traffic Pattern Type #" + to_string(patternId + 1), false, false);
- m_trafficPatterns[patternId].printTrafficConfiguration(m_logger);
- m_logger.log("", false, false);
- }
- }
- else {
- m_logger.log("ERROR: Unable to open traffic configuration file: " + m_configurationFile, false, true);
- exit(2);
- }
- }
-
- void
- initializeTrafficConfiguration()
- {
- namespace fs = boost::filesystem;
-
- fs::path configPath(m_configurationFile);
- if (fs::exists(configPath)) {
- if (fs::is_regular_file(configPath)) {
- parseConfigurationFile();
- }
- else {
- m_logger.log("ERROR: Traffic configuration file is not a regular file: " +
- m_configurationFile, false, true);
- exit(2);
- }
- }
- else {
- m_logger.log("ERROR: Traffic configuration file does not exist: " +
- m_configurationFile, false, true);
- exit(2);
- }
- }
-
static std::string
getRandomByteString(std::size_t length)
{
@@ -501,7 +430,5 @@
server.setQuietLogging();
}
- server.run();
-
- return server.hasError() ? 1 : 0;
+ return server.run();
}
diff --git a/src/util.hpp b/src/util.hpp
index 65052d8..bafdc39 100644
--- a/src/util.hpp
+++ b/src/util.hpp
@@ -21,13 +21,17 @@
#ifndef NTG_UTIL_HPP
#define NTG_UTIL_HPP
+#include "logger.hpp"
+
#include <cctype>
#include <string>
+#include <boost/algorithm/string/predicate.hpp>
+
namespace ndn {
static inline bool
-parseParameterAndValue(const std::string& input, std::string& parameter, std::string& value)
+extractParameterAndValue(const std::string& input, std::string& parameter, std::string& value)
{
static const std::string allowedCharacters = ":/+._-%";
parameter = "";
@@ -56,6 +60,65 @@
return !parameter.empty() && !value.empty() && i == input.length();
}
+static inline bool
+parseBoolean(const std::string& input)
+{
+ if (boost::iequals(input, "no") || boost::iequals(input, "off") ||
+ boost::iequals(input, "false") || input == "0")
+ return false;
+
+ if (boost::iequals(input, "yes") || boost::iequals(input, "on") ||
+ boost::iequals(input, "true") || input == "1")
+ return true;
+
+ throw std::invalid_argument("'" + input + "' is not a valid boolean value");
+}
+
+template<typename TrafficConfigurationType>
+static inline bool
+readConfigurationFile(const std::string& filename,
+ std::vector<TrafficConfigurationType>& patterns,
+ Logger& logger)
+{
+ std::ifstream patternFile(filename);
+ if (!patternFile) {
+ logger.log("ERROR: Unable to open traffic configuration file: " + filename, false, true);
+ return false;
+ }
+
+ logger.log("Reading traffic configuration file: " + filename, true, true);
+
+ int lineNumber = 0;
+ std::string patternLine;
+ while (getline(patternFile, patternLine)) {
+ lineNumber++;
+ if (std::isalpha(patternLine[0])) {
+ TrafficConfigurationType trafficConf;
+ bool shouldSkipLine = false;
+ if (trafficConf.parseConfigurationLine(patternLine, logger, lineNumber)) {
+ while (getline(patternFile, patternLine) && std::isalpha(patternLine[0])) {
+ lineNumber++;
+ if (!trafficConf.parseConfigurationLine(patternLine, logger, lineNumber)) {
+ shouldSkipLine = true;
+ break;
+ }
+ }
+ lineNumber++;
+ }
+ else {
+ shouldSkipLine = true;
+ }
+ if (!shouldSkipLine) {
+ if (trafficConf.checkTrafficDetailCorrectness()) {
+ patterns.push_back(std::move(trafficConf));
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
} // namespace ndn
#endif // NTG_UTIL_HPP