Refactor config file parsing and improve error handling

Change-Id: I8a54ba1f0d414bea70923e0f45ca354ac7e957a3
This commit is contained in:
Davide Pesavento committed 2019-01-26 16:22:38 -05:00
1 parent 032c98004f
commit 306e5bc606
5 files changed
+167 -248

No files matched your search

+12 -13
View File
@@ -2,20 +2,19 @@
# THIS IS A SAMPLE CLIENT INTEREST TRAFFIC CONFIGURATION FILE
#
# * TO BE USED TO GENERATE INTEREST MESSAGES BASED ON A PROBABILITY
# PATTERN.
# * EVERY INIVIDUAL PATTERN DESCRIPTION MUST BE SEPARATED BY ONE
# PATTERN
# * EVERY INDIVIDUAL PATTERN DESCRIPTION MUST BE SEPARATED BY ONE
# OR MORE '#' CHARACTERS FOR THE TOOL TO DISTINGUISH THEM
# INDIVIDUALLY
# * THE FOLLOWING PARAMETERS MAY BE ADDED FOR EVERY TRAFFIC PATTERN
# * (Mandatory) NEXT TO A PARAMETER MEANS EVERY PATTERN SHOULD HAVE
# IT FOR BEING CONSIDERED VALID
# (Optional) MEANS OTHERWISE
# * ALSO PROVIDED ARE VALID VALUES POSSIBLE FOR EACH PARAMETER
# * PLEASE ENSURE THAT THE SUM OF TrafficPercentage FOR ALL DECLARED
# PATTERNS DOES NOT EXCEED 100 IN ORDER TO MAINTAIN CORRECT BEHAVIOR
# * NNI STANDS FOR NON-NEGATIVE INTEGER
# * 'Mandatory' ARE PARAMETERS THAT EVERY PATTERN MUST HAVE IN ORDER
# TO BE CONSIDERED VALID
# * 'Boolean' ACCEPTS EITHER 0/false/no/off OR 1/true/yes/on AS VALUE
# * 'NNI' STANDS FOR NON-NEGATIVE INTEGER
# * RANGE OF POSSIBLE VALUES IS SPECIFIED IN []
# * PLEASE ENSURE THAT THE SUM OF 'TrafficPercentage' FOR ALL DECLARED
# PATTERNS DOES NOT EXCEED 100 IN ORDER TO MAINTAIN CORRECT BEHAVIOR
#
# (Mandatory)
#TrafficPercentage=NNI [0-100]
#Name=NDN Name
@@ -23,10 +22,10 @@
# (Optional)
#NameAppendBytes=NNI [>0]
#NameAppendSequenceNumber=NNI [>=0]
#MustBeFresh=NNI [0-1]
#MustBeFresh=Boolean
#NonceDuplicationPercentage=NNI [0-100]
#InterestLifetime=NNI [Milliseconds]
#NextHopFaceId=NNI
#InterestLifetime=Milliseconds [>=0]
#NextHopFaceId=NNI [>0]
#ExpectedContent=String
##########
+8 -9
View File
@@ -3,26 +3,25 @@
#
# * TO BE USED TO CONFIGURE RESPONSE TO INTERESTS
# * MULTIPLE SERVER PREFIXES CAN BE CONFIGURED FOR BEING HANDLED
# * EVERY INIVIDUAL PATTERN DESCRIPTION MUST BE SEPARATED BY ONE
# * EVERY INDIVIDUAL PATTERN DESCRIPTION MUST BE SEPARATED BY ONE
# OR MORE '#' CHARACTERS FOR THE TOOL TO DISTINGUISH THEM
# INDIVIDUALLY
# * THE FOLLOWING PARAMETERS MAY BE ADDED FOR EVERY TRAFFIC PATTERN
# * (Mandatory) NEXT TO A PARAMETER MEANS EVERY PATTERN SHOULD HAVE
# IT FOR BEING CONSIDERED VALID
# (Optional) MEANS OTHERWISE
# * ALSO PROVIDED ARE VALID VALUES POSSIBLE FOR EACH PARAMETER
# * NNI STANDS FOR NON-NEGATIVE INTEGER
# * 'Mandatory' ARE PARAMETERS THAT EVERY PATTERN MUST HAVE IN ORDER
# TO BE CONSIDERED VALID
# * 'Boolean' ACCEPTS EITHER 0/false/no/off OR 1/true/yes/on AS VALUE
# * 'NNI' STANDS FOR NON-NEGATIVE INTEGER
# * RANGE OF POSSIBLE VALUES IS SPECIFIED IN []
#
# (Mandatory)
#Name=NDN Name
#
# (Optional)
#ContentDelay=Milliseconds [>=0]
#FreshnessPeriod=Milliseconds [>=0]
#ContentType=NNI [>=0]
#FreshnessPeriod=NNI [milliseconds]
#ContentBytes=NNI [>0]
#Content=String
#ContentDelay=NNI [milliseconds]
#SigningInfo=String [examples below]
##########
+52 -121
View File
@@ -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 @@ public:
{
}
bool
hasError() const
{
return m_hasError;
}
void
setMaximumInterests(uint64_t maxInterests)
{
@@ -83,15 +74,30 @@ public:
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 @@ public:
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 @@ private:
std::string detail;
detail += "TrafficPercentage=" + to_string(m_trafficPercentage) + ", ";
if (!m_name.empty())
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 @@ private:
}
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")
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")
}
else if (parameter == "Name") {
m_name = value;
else if (parameter == "NameAppendBytes")
}
else if (parameter == "NameAppendBytes") {
m_nameAppendBytes = std::stoul(value);
else if (parameter == "NameAppendSequenceNumber")
}
else if (parameter == "NameAppendSequenceNumber") {
m_nameAppendSeqNum = std::stoull(value);
else if (parameter == "MustBeFresh")
m_mustBeFresh = bool(std::stoul(value));
else if (parameter == "NonceDuplicationPercentage")
}
else if (parameter == "MustBeFresh") {
m_mustBeFresh = parseBoolean(value);
}
else if (parameter == "NonceDuplicationPercentage") {
m_nonceDuplicationPercentage = std::stoul(value);
else if (parameter == "InterestLifetime")
}
else if (parameter == "InterestLifetime") {
m_interestLifetime = time::milliseconds(std::stoul(value));
else if (parameter == "NextHopFaceId")
}
else if (parameter == "NextHopFaceId") {
m_nextHopFaceId = std::stoull(value);
else if (parameter == "ExpectedContent")
}
else if (parameter == "ExpectedContent") {
m_expectedContent = value;
else
logger.log("Line " + to_string(lineNumber) +
" - Unknown parameter '" + parameter + "'", false, true);
}
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 @@ private:
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 @@ private:
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 @@ private:
}
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 @@ main(int argc, char* argv[])
client.setQuietLogging();
}
client.run();
return client.hasError() ? 1 : 0;
return client.run();
}
+31 -104
View File
@@ -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 @@ public:
{
}
bool
hasError() const
{
return m_hasError;
}
void
setMaximumInterests(uint64_t maxInterests)
{
@@ -82,15 +74,30 @@ public:
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 @@ public:
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,10 +159,15 @@ private:
}
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 (!extractParameterAndValue(line, parameter, value)) {
logger.log("Line " + to_string(lineNumber) + " - Invalid syntax: " + line,
false, true);
return false;
}
if (parameter == "Name") {
m_name = value;
}
@@ -177,14 +190,8 @@ private:
m_signingInfo = security::SigningInfo(value);
}
else {
logger.log("Line " + to_string(lineNumber) +
" - Unknown parameter '" + parameter + "'", false, true);
}
}
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 @@ private:
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 @@ main(int argc, char* argv[])
server.setQuietLogging();
}
server.run();
return server.hasError() ? 1 : 0;
return server.run();
}
+64 -1
View File
@@ -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 @@ parseParameterAndValue(const std::string& input, std::string& parameter, std::st
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