Client Tool 70%, Server Tool 50% Complete
diff --git a/ndn-traffic-client.cpp b/ndn-traffic-client.cpp
index ed243be..f28b5d6 100644
--- a/ndn-traffic-client.cpp
+++ b/ndn-traffic-client.cpp
@@ -1,25 +1,109 @@
/**
*
- * Copyright (C) 2013 University of Arizona.
+ * Copyright (C) 2014 University of Arizona.
* @author: Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
*
*/
+#include <string>
+#include <sstream>
+#include <fstream>
+#include <vector>
+#include <boost/asio.hpp>
+#include <boost/filesystem.hpp>
+
+#include <ndn-cpp-dev/face.hpp>
#include <ndn-cpp-dev/security/key-chain.hpp>
using namespace ndn;
+class Logger
+{
+public:
+
+ Logger()
+ {
+ logLocation_ = "";
+ }
+
+ void
+ shutdownLogger()
+ {
+ if (logFile_.is_open())
+ logFile_.close();
+ }
+
+ void
+ log( std::string logLine )
+ {
+ if( logLocation_.length() > 0 )
+ {
+ logFile_ << logLine << std::endl;
+ logFile_.flush();
+ }
+ else
+ std::cout << logLine << std::endl;
+ }
+
+ void
+ initializeLog( std::string instanceId )
+ {
+ char* variableValue = std::getenv("NDN_TRAFFIC_LOGFOLDER");
+ std::string logFilename;
+ logLocation_ = "";
+ if (variableValue != NULL)
+ logLocation_ = variableValue;
+ if (boost::filesystem::exists(boost::filesystem::path(logLocation_)))
+ {
+ if (boost::filesystem::is_directory(boost::filesystem::path(logLocation_)))
+ {
+ logFilename = logLocation_+"/NDNTrafficClient_"+instanceId+".log";
+ logFile_.open(logFilename.c_str(), std::ofstream::out | std::ofstream::trunc);
+ if (logFile_.is_open())
+ std::cout << "Log File Initialized: " << logFilename << std::endl;
+ else
+ {
+ std::cout << "ERROR - Unable To Initialize A Log File At: " << logLocation_ << std::endl
+ << "Using Default Output For Logging." << std::endl;
+ logLocation_ = "";
+ }
+ }
+ else
+ {
+ std::cout << "Environment Variable NDN_TRAFFIC_LOGFOLDER Should Be A Folder." << std::endl
+ << "Using Default Output For Logging." << std::endl;
+ logLocation_ = "";
+ }
+ }
+ else
+ {
+ std::cout << "Environment Variable NDN_TRAFFIC_LOGFOLDER Not Set." << std::endl
+ << "Using Default Output For Logging." << std::endl;
+ logLocation_ = "";
+ }
+ }
+
+private:
+
+ std::string logLocation_;
+ std::ofstream logFile_;
+
+};
+
class NdnTrafficClient
{
public:
NdnTrafficClient( char* programName )
{
+ std::srand(std::time(0));
+ instanceId_ = toString(std::rand());
programName_ = programName;
interestInterval_ = getDefaultInterestInterval();
interestCount_ = getDefaultInterestCount();
- prefix_ = "";
configurationFile_ = "";
+ ioService_ = ptr_lib::make_shared<boost::asio::io_service>();
+ face_ = Face(ioService_);
}
NdnTrafficClient()
@@ -27,18 +111,195 @@
{
}
+ class InterestTrafficConfiguration
+ {
+ public:
+
+ InterestTrafficConfiguration()
+ {
+ trafficPercentage = -1;
+ name = "";
+ nameAppendBytes = -1;
+ nameAppendSequenceNumber = -1;
+ minSuffixComponents = -1;
+ maxSuffixComponents = -1;
+ excludeBefore = "";
+ excludeAfter = "";
+ excludeBeforeBytes = -1;
+ excludeAfterBytes = -1;
+ childSelector = -1;
+ mustBeFresh = -1;
+ nonceDuplicationPercentage = -1;
+ scope = -1;
+ interestLifetime = -1;
+ }
+
+ void
+ printTrafficConfiguration( Logger& logger )
+ {
+ std::string detail;
+ detail = "";
+ if (trafficPercentage > 0)
+ detail += "TrafficPercentage="+toString(trafficPercentage)+", ";
+ if (name != "")
+ detail += "Name="+name+", ";
+ if (nameAppendBytes>0)
+ detail += "NameAppendBytes="+toString(nameAppendBytes)+", ";
+ if (nameAppendSequenceNumber>0)
+ detail += "NameAppendSequenceNumber="+toString(nameAppendSequenceNumber)+", ";
+ if (minSuffixComponents>0)
+ detail += "MinSuffixComponents="+toString(minSuffixComponents)+", ";
+ if (maxSuffixComponents>0)
+ detail += "MaxSuffixComponents="+toString(maxSuffixComponents)+", ";
+ if (excludeBefore != "")
+ detail += "ExcludeBefore="+excludeBefore+", ";
+ if (excludeAfter != "")
+ detail += "ExcludeAfter="+excludeAfter+", ";
+ if (excludeBeforeBytes > 0)
+ detail += "ExcludeBeforeBytes="+toString(excludeBeforeBytes)+", ";
+ if (excludeAfterBytes > 0)
+ detail += "ExcludeAfterBytes="+toString(excludeAfterBytes)+", ";
+ if (childSelector > 0)
+ detail += "ChildSelector="+toString(childSelector)+", ";
+ if (mustBeFresh > 0)
+ detail += "MustBeFresh="+toString(mustBeFresh)+", ";
+ if (nonceDuplicationPercentage > 0)
+ detail += "NonceDuplicationPercentage="+toString(nonceDuplicationPercentage)+", ";
+ if (scope > 0)
+ detail += "Scope="+toString(scope)+", ";
+ if (interestLifetime > 0)
+ detail += "InterestLifetime="+toString(interestLifetime)+", ";
+ if (detail.length() >= 0)
+ detail = detail.substr(0, detail.length()-2);
+ logger.log(detail);
+ }
+
+ bool
+ extractParameterValue( std::string detail, std::string& parameter, std::string& value )
+ {
+ int i;
+ std::string allowedCharacters = ":/+._-%";
+ parameter = "";
+ value = "";
+ i = 0;
+ while (detail[i] != '=' && i < detail.length())
+ {
+ parameter += detail[i];
+ i++;
+ }
+ if (i == detail.length())
+ return false;
+ i++;
+ while ((std::isalnum(detail[i]) || allowedCharacters.find(detail[i]) != std::string::npos) && i < detail.length())
+ {
+ value += detail[i];
+ i++;
+ }
+ if(parameter == "" || value == "")
+ return false;
+ return true;
+ }
+
+ bool
+ processConfigurationDetail( std::string detail, Logger& logger, int lineNumber )
+ {
+ std::string parameter, value;
+ if (extractParameterValue(detail, parameter, value))
+ {
+ if (parameter == "TrafficPercentage")
+ trafficPercentage = toInteger(value);
+ else if (parameter == "Name")
+ name = value;
+ else if (parameter == "NameAppendBytes")
+ nameAppendBytes = toInteger(value);
+ else if (parameter == "NameAppendSequenceNumber")
+ nameAppendSequenceNumber = toInteger(value);
+ else if (parameter == "MinSuffixComponents")
+ minSuffixComponents = toInteger(value);
+ else if (parameter == "MaxSuffixComponents")
+ maxSuffixComponents = toInteger(value);
+ else if (parameter == "ExcludeBefore")
+ excludeBefore = value;
+ else if (parameter == "ExcludeAfter")
+ excludeAfter = value;
+ else if (parameter == "ExcludeBeforeBytes")
+ excludeBeforeBytes = toInteger(value);
+ else if (parameter == "ExcludeAfterBytes")
+ excludeAfterBytes = toInteger(value);
+ else if (parameter == "ChildSelector")
+ childSelector = toInteger(value);
+ else if (parameter == "MustBeFresh")
+ mustBeFresh = toInteger(value);
+ else if (parameter == "NonceDuplicationPercentage")
+ nonceDuplicationPercentage = toInteger(value);
+ else if (parameter == "Scope")
+ scope = toInteger(value);
+ else if (parameter == "InterestLifetime")
+ interestLifetime = toInteger(value);
+ else
+ logger.log("Line "+toString(lineNumber)+" \t- Invalid Parameter='"+parameter+"'");
+ }
+ else
+ {
+ logger.log("Line "+toString(lineNumber)+" \t: Improper Traffic Configuration Line- "+detail);
+ return false;
+ }
+ return true;
+ }
+
+ bool
+ checkTrafficDetailCorrectness()
+ {
+ return true;
+ }
+
+ int trafficPercentage;
+ std::string name;
+ int nameAppendBytes;
+ int nameAppendSequenceNumber;
+ int minSuffixComponents;
+ int maxSuffixComponents;
+ std::string excludeBefore;
+ std::string excludeAfter;
+ int excludeBeforeBytes;
+ int excludeAfterBytes;
+ int childSelector;
+ int mustBeFresh;
+ int nonceDuplicationPercentage;
+ int scope;
+ int interestLifetime;
+
+ };
+
+ static std::string
+ toString( int integerValue )
+ {
+ std::stringstream stream;
+ stream << integerValue;
+ return stream.str();
+ }
+
+ static int
+ toInteger( std::string stringValue )
+ {
+ int integerValue;
+ std::stringstream stream(stringValue);
+ stream >> integerValue;
+ return integerValue;
+ }
+
void
usage()
{
std::cout << "\nUsage: " << programName_ << " Printing Usage"
- "\n\n";
+ << std::endl << std::endl;
exit(1);
}
int
getDefaultInterestInterval()
{
- return -1;
+ return 1000;
}
int
@@ -47,15 +308,6 @@
return -1;
}
- bool
- isPrefixSet()
- {
- if ( prefix_.length() > 0 )
- return true;
- else
- return false;
- }
-
void
setInterestInterval( int interestInterval )
{
@@ -73,25 +325,137 @@
}
void
- setPrefix( char* prefix )
- {
- prefix_ = prefix;
- }
-
- void
setConfigurationFile( char* configurationFile )
{
configurationFile_ = configurationFile;
}
+ void
+ signalHandler()
+ {
+ logger_.shutdownLogger();
+ face_.shutdown();
+ ioService_.reset();
+ exit(1);
+ }
+
+ bool
+ checkTrafficPatternCorrectness()
+ {
+ return true;
+ }
+
+ void
+ analyzeConfigurationFile()
+ {
+ int patternId;
+ int lineNumber;
+ bool skipLine;
+ std::string patternLine;
+ std::ifstream patternFile;
+ logger_.log("Analyzing Traffic Configuration File: " + configurationFile_);
+ patternFile.open(configurationFile_.c_str());
+ if (patternFile.is_open())
+ {
+ patternId = 0;
+ lineNumber = 0;
+ while (getline(patternFile, patternLine))
+ {
+ lineNumber++;
+ if (std::isalpha(patternLine[0]))
+ {
+ InterestTrafficConfiguration interestData;
+ skipLine = false;
+ patternId++;
+ if (interestData.processConfigurationDetail(patternLine, logger_, lineNumber))
+ {
+ while (getline(patternFile, patternLine) && std::isalpha(patternLine[0]))
+ {
+ lineNumber++;
+ if (!interestData.processConfigurationDetail(patternLine, logger_, lineNumber))
+ {
+ skipLine = true;
+ break;
+ }
+ }
+ lineNumber++;
+ }
+ else
+ skipLine = true;
+ if( !skipLine )
+ {
+ if (interestData.checkTrafficDetailCorrectness())
+ trafficPattern_.push_back(interestData);
+ }
+ }
+ }
+ patternFile.close();
+ if (!checkTrafficPatternCorrectness())
+ {
+ logger_.log("ERROR - Traffic Configuration Provided Is Not Proper- " + configurationFile_);
+ logger_.shutdownLogger();
+ std::cout << "ERROR - Check Log File For Details." << std::endl;
+ exit(1);
+ }
+ for (patternId = 0; patternId < trafficPattern_.size(); patternId++)
+ trafficPattern_[patternId].printTrafficConfiguration(logger_);
+ }
+ else
+ {
+ logger_.log("ERROR - Unable To Open Traffic Configuration File: " + configurationFile_);
+ logger_.shutdownLogger();
+ std::cout << "ERROR - Check Log File For Details." << std::endl;
+ exit(1);
+ }
+ }
+
+ void
+ initializeTrafficConfiguration()
+ {
+ if (boost::filesystem::exists(boost::filesystem::path(configurationFile_)))
+ {
+ if(boost::filesystem::is_regular_file(boost::filesystem::path(configurationFile_)))
+ {
+ analyzeConfigurationFile();
+ }
+ else
+ {
+ logger_.log("ERROR - Traffic Configuration File Is Not A Regular File: " + configurationFile_);
+ logger_.shutdownLogger();
+ std::cout << "ERROR - Check Log File For Details." << std::endl;
+ exit(1);
+ }
+ }
+ else
+ {
+ logger_.log("ERROR - Traffic Configuration File Does Not Exist: " + configurationFile_);
+ logger_.shutdownLogger();
+ std::cout << "ERROR - Check Log File For Details." << std::endl;
+ exit(1);
+ }
+ }
+
+ void
+ initialize()
+ {
+ boost::asio::signal_set signalSet(*ioService_, SIGINT, SIGTERM);
+ signalSet.async_wait(boost::bind(&NdnTrafficClient::signalHandler, this));
+ logger_.initializeLog(instanceId_);
+ initializeTrafficConfiguration();
+ }
+
private:
KeyChain keyChain_;
std::string programName_;
+ std::string instanceId_;
int interestInterval_;
int interestCount_;
- std::string prefix_;
+ Logger logger_;
std::string configurationFile_;
+ ptr_lib::shared_ptr<boost::asio::io_service> ioService_;
+ std::vector<InterestTrafficConfiguration> trafficPattern_;
+ Face face_;
};
@@ -99,7 +463,7 @@
{
int option;
NdnTrafficClient ndnTrafficClient (argv[0]);
- while ((option = getopt(argc, argv, "hi:c:p:")) != -1) {
+ while ((option = getopt(argc, argv, "hi:c:")) != -1) {
switch (option) {
case 'h' :
ndnTrafficClient.usage();
@@ -110,9 +474,6 @@
case 'c' :
ndnTrafficClient.setInterestCount(atoi(optarg));
break;
- case 'p' :
- ndnTrafficClient.setPrefix(optarg);
- break;
default :
ndnTrafficClient.usage();
break;
@@ -122,10 +483,11 @@
argc -= optind;
argv += optind;
- if (argv[0] == NULL && !ndnTrafficClient.isPrefixSet() )
+ if (argv[0] == NULL)
ndnTrafficClient.usage();
ndnTrafficClient.setConfigurationFile(argv[0]);
+ ndnTrafficClient.initialize();
return 0;
}