doc+src: More reorganization and fixing of README
Change-Id: I8ff2dcdabd78f38cc0d5b826883121a9444ef664
diff --git a/src/ndn-traffic-client.cpp b/src/ndn-traffic-client.cpp
new file mode 100644
index 0000000..135d4ce
--- /dev/null
+++ b/src/ndn-traffic-client.cpp
@@ -0,0 +1,828 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2014 University of Arizona.
+ *
+ * GNU 3.0 License, see the LICENSE file for more information
+ *
+ * Author: Jerald Paul Abraham <jeraldabraham@email.arizona.edu>
+ */
+
+#include <string>
+#include <sstream>
+#include <fstream>
+#include <vector>
+
+#include "logger.hpp"
+
+#include <boost/asio.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
+#include <ndn-cpp-dev/face.hpp>
+#include <ndn-cpp-dev/exclude.hpp>
+#include <ndn-cpp-dev/name-component.hpp>
+#include <ndn-cpp-dev/security/key-chain.hpp>
+
+namespace ndn {
+
+class NdnTrafficClient
+{
+public:
+ NdnTrafficClient(char* programName)
+ : m_logger("NDNTrafficClient")
+ , ioService_(new boost::asio::io_service)
+ , face_(ioService_)
+ , keyChain_()
+ {
+ std::srand(std::time(0));
+ instanceId_ = toString(std::rand());
+ programName_ = programName;
+ interestInterval_ = getDefaultInterestInterval();
+ interestCount_ = getDefaultInterestCount();
+ configurationFile_ = "";
+ totalInterestSent_ = 0;
+ totalInterestReceived_ = 0;
+ minimumInterestRoundTripTime_ = std::numeric_limits<double>::max();
+ maximumInterestRoundTripTime_ = 0;
+ totalInterestRoundTripTime_ = 0;
+ }
+
+ 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;
+ totalInterestSent = 0;
+ totalInterestReceived = 0;
+ minimumInterestRoundTripTime = std::numeric_limits<double>::max();
+ maximumInterestRoundTripTime = 0;
+ totalInterestRoundTripTime = 0;
+ contentInconsistencies = 0;
+ expectedContent = "";
+ }
+
+ 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 (expectedContent != "")
+ detail += "ExpectedContent="+expectedContent+", ";
+ if (detail.length() >= 2)
+ detail = detail.substr(0, detail.length()-2);
+ logger.log(detail, false, false);
+ }
+
+ bool
+ extractParameterValue(const 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(const 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 if (parameter == "ExpectedContent")
+ expectedContent = value;
+ else
+ logger.log("Line "+toString(lineNumber) +
+ " \t- Invalid Parameter='"+parameter+"'", false, true);
+ }
+ else
+ {
+ logger.log("Line "+toString(lineNumber) +
+ " \t- Improper Traffic Configuration Line- "+detail, false, true);
+ 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;
+ int totalInterestSent;
+ int totalInterestReceived;
+ double minimumInterestRoundTripTime;
+ double maximumInterestRoundTripTime;
+ double totalInterestRoundTripTime;
+ int contentInconsistencies;
+ std::string expectedContent;
+ }; // class InterestTrafficConfiguration
+
+ int
+ getDefaultInterestLifetime()
+ {
+ return 4000;
+ }
+
+ static std::string
+ toString(int integerValue)
+ {
+ std::stringstream stream;
+ stream << integerValue;
+ return stream.str();
+ }
+
+ static std::string
+ toString(double doubleValue)
+ {
+ std::stringstream stream;
+ stream << doubleValue;
+ return stream.str();
+ }
+
+ static int
+ toInteger(const std::string& stringValue)
+ {
+ int integerValue;
+ std::stringstream stream(stringValue);
+ stream >> integerValue;
+ return integerValue;
+ }
+
+ void
+ usage()
+ {
+
+ std::cout << "\nUsage: " << programName_ << " [options] <Traffic_Configuration_File>\n"
+ "Generate Interest Traffic as per provided Traffic Configuration File\n"
+ "Interests are continuously generated unless a total number is specified.\n"
+ "Set environment variable NDN_TRAFFIC_LOGFOLDER for redirecting output to a log.\n"
+ " [-i interval] - set interest generation interval in milliseconds (minimum "
+ << getDefaultInterestInterval() << " milliseconds)\n"
+ " [-c count] - set total number of interests to be generated\n"
+ " [-h] - print help and exit\n\n";
+ exit(1);
+
+ }
+
+ int
+ getDefaultInterestInterval()
+ {
+ return 1000;
+ }
+
+ int
+ getDefaultInterestCount()
+ {
+ return -1;
+ }
+
+ void
+ setInterestInterval( int interestInterval )
+ {
+ if (interestInterval < 0)
+ usage();
+ interestInterval_ = interestInterval;
+ }
+
+ void
+ setInterestCount( int interestCount )
+ {
+ if (interestCount < 0)
+ usage();
+ interestCount_ = interestCount;
+ }
+
+ void
+ setConfigurationFile( char* configurationFile )
+ {
+ configurationFile_ = configurationFile;
+ }
+
+ void
+ signalHandler()
+ {
+ m_logger.shutdownLogger();
+ face_.shutdown();
+ ioService_.reset();
+ logStatistics();
+ exit(1);
+ }
+
+ void
+ logStatistics()
+ {
+ int patternId;
+ double loss, average, inconsistency;
+
+ m_logger.log("\n\n== Interest Traffic Report ==\n", false, true);
+ m_logger.log("Total Traffic Pattern Types = " + toString((int)trafficPattern_.size()), false, true);
+ m_logger.log("Total Interests Sent = " + toString(totalInterestSent_), false, true);
+ m_logger.log("Total Responses Received = " + toString(totalInterestReceived_), false, true);
+ if (totalInterestSent_ > 0)
+ loss = (totalInterestSent_-totalInterestReceived_)*100.0/totalInterestSent_;
+ else
+ loss = 0;
+ m_logger.log("Total Interest Loss = " + toString(loss)+"%", false, true);
+ if (totalInterestReceived_ > 0)
+ {
+ average = totalInterestRoundTripTime_/totalInterestReceived_;
+ inconsistency = contentInconsistencies_*100.0/totalInterestReceived_;
+ }
+ else
+ {
+ average = 0;
+ inconsistency = 0;
+ }
+ m_logger.log("Total Data Inconsistency = " + toString(inconsistency)+"%", false, true);
+ m_logger.log("Total Round Trip Time = " +
+ toString(totalInterestRoundTripTime_)+"ms", false, true);
+ m_logger.log("Average Round Trip Time = " + toString(average)+"ms\n", false, true);
+
+ for (patternId=0; patternId<trafficPattern_.size(); patternId++)
+ {
+ m_logger.log("Traffic Pattern Type #" + toString(patternId+1), false, true);
+ trafficPattern_[patternId].printTrafficConfiguration(m_logger);
+ m_logger.log("Total Interests Sent = " +
+ toString(trafficPattern_[patternId].totalInterestSent), false, true);
+ m_logger.log("Total Responses Received = " +
+ toString(trafficPattern_[patternId].totalInterestReceived), false, true);
+ if (trafficPattern_[patternId].totalInterestSent > 0)
+ {
+ loss = (trafficPattern_[patternId].totalInterestSent -
+ trafficPattern_[patternId].totalInterestReceived);
+ loss *= 100.0;
+ loss /= trafficPattern_[patternId].totalInterestSent;
+ }
+ else
+ loss = 0;
+ m_logger.log("Total Interest Loss = " + toString(loss)+"%", false, true);
+ if (trafficPattern_[patternId].totalInterestReceived > 0)
+ {
+ average = (trafficPattern_[patternId].totalInterestRoundTripTime /
+ trafficPattern_[patternId].totalInterestReceived);
+ inconsistency = trafficPattern_[patternId].contentInconsistencies;
+ inconsistency = inconsistency * 100.0 / trafficPattern_[patternId].totalInterestReceived;
+ }
+ else
+ {
+ average = 0;
+ inconsistency = 0;
+ }
+ m_logger.log("Total Data Inconsistency = " + toString(inconsistency)+"%", false, true);
+ m_logger.log("Total Round Trip Time = " +
+ toString(trafficPattern_[patternId].totalInterestRoundTripTime)+"ms",
+ false, true);
+ m_logger.log("Average Round Trip Time = " + toString(average)+"ms\n", false, true);
+ }
+ }
+
+ bool
+ checkTrafficPatternCorrectness()
+ {
+ return true;
+ }
+
+ void
+ analyzeConfigurationFile()
+ {
+ int patternId;
+ int lineNumber;
+ bool skipLine;
+ std::string patternLine;
+ std::ifstream patternFile;
+ m_logger.log("Analyzing Traffic Configuration File: " + configurationFile_, true, true);
+ 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, m_logger, lineNumber))
+ {
+ while (getline(patternFile, patternLine) && std::isalpha(patternLine[0]))
+ {
+ lineNumber++;
+ if (!interestData.processConfigurationDetail(patternLine,
+ m_logger, lineNumber))
+ {
+ skipLine = true;
+ break;
+ }
+ }
+ lineNumber++;
+ }
+ else
+ skipLine = true;
+ if( !skipLine )
+ {
+ if (interestData.checkTrafficDetailCorrectness())
+ trafficPattern_.push_back(interestData);
+ }
+ }
+ }
+ patternFile.close();
+ if (!checkTrafficPatternCorrectness())
+ {
+ m_logger.log("ERROR - Traffic Configuration Provided Is Not Proper- " +
+ configurationFile_, false, true);
+ m_logger.shutdownLogger();
+ exit(1);
+ }
+ m_logger.log("Traffic Configuration File Processing Completed\n", true, false);
+ for (patternId=0; patternId<trafficPattern_.size(); patternId++)
+ {
+ m_logger.log("Traffic Pattern Type #"+toString(patternId+1), false, false);
+ trafficPattern_[patternId].printTrafficConfiguration(m_logger);
+ m_logger.log("", false, false);
+ }
+ }
+ else
+ {
+ m_logger.log("ERROR - Unable To Open Traffic Configuration File: " +
+ configurationFile_, false, true);
+ m_logger.shutdownLogger();
+ exit(1);
+ }
+ }
+
+ void
+ initializeTrafficConfiguration()
+ {
+ if (boost::filesystem::exists(boost::filesystem::path(configurationFile_)))
+ {
+ if(boost::filesystem::is_regular_file(boost::filesystem::path(configurationFile_)))
+ {
+ analyzeConfigurationFile();
+ }
+ else
+ {
+ m_logger.log("ERROR - Traffic Configuration File Is Not A Regular File: " +
+ configurationFile_, false, true);
+ m_logger.shutdownLogger();
+ exit(1);
+ }
+ }
+ else
+ {
+ m_logger.log("ERROR - Traffic Configuration File Does Not Exist: " +
+ configurationFile_, false, true);
+ m_logger.shutdownLogger();
+ exit(1);
+ }
+ }
+
+ int
+ getOldNonce()
+ {
+ int randomNonceKey;
+ if (nonceList_.size() == 0)
+ return getNewNonce();
+ std::srand(std::time(0));
+ randomNonceKey = std::rand() % nonceList_.size();
+ return nonceList_[randomNonceKey];
+ }
+
+ int
+ getNewNonce()
+ {
+ int randomNonceKey, i;
+ bool isOld;
+ isOld = true;
+ std::srand(std::time(0));
+
+ //Performance Enhancement
+ if (nonceList_.size() > 1000)
+ nonceList_.clear();
+
+ do
+ {
+ randomNonceKey = std::rand();
+ isOld = false;
+ for (i=0; i<nonceList_.size(); i++)
+ if (nonceList_[i] == randomNonceKey)
+ isOld = true;
+ } while(isOld);
+ nonceList_.push_back(randomNonceKey);
+ return randomNonceKey;
+ }
+
+ static std::string
+ getRandomByteString( int randomSize )
+ {
+ int i;
+ std::string characterSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvw0123456789";
+ std::string randomData;
+ for (i=0; i<randomSize; i++)
+ randomData += characterSet[std::rand() % characterSet.length()];
+ return randomData;
+ }
+
+ void
+ onData( ndn::Face &face,
+ const ndn::Interest& interest,
+ ndn::Data& data,
+ int globalReference,
+ int localReference,
+ int patternId,
+ boost::posix_time::ptime sentTime )
+ {
+ double roundTripTime;
+ int receivedContentLength;
+ std::string receivedContent;
+ std::string logLine;
+ logLine = "";
+ logLine += "Data Received - PatternType="+toString(patternId+1);
+ logLine += ", GlobalID="+toString(globalReference);
+ logLine += ", LocalID="+toString(localReference);
+ logLine += ", Name="+interest.getName().toUri();
+ boost::posix_time::time_duration roundTripDuration;
+ totalInterestReceived_++;
+ trafficPattern_[patternId].totalInterestReceived++;
+ if (trafficPattern_[patternId].expectedContent != "")
+ {
+ receivedContent = (char*)(data.getContent().value());
+ receivedContentLength = data.getContent().value_size();
+ receivedContent = receivedContent.substr(0, receivedContentLength);
+ if (receivedContent != trafficPattern_[patternId].expectedContent)
+ {
+ contentInconsistencies_++;
+ trafficPattern_[patternId].contentInconsistencies++;
+ logLine += ", IsConsistent=No";
+ }
+ else
+ logLine += ", IsConsistent=Yes";
+ }
+ else
+ logLine += ", IsConsistent=NotChecked";
+ m_logger.log(logLine, true, false);
+ roundTripDuration = boost::posix_time::microsec_clock::local_time() - sentTime;
+ roundTripTime = roundTripDuration.total_microseconds()/1000.0;
+ if (minimumInterestRoundTripTime_ > roundTripTime)
+ minimumInterestRoundTripTime_ = roundTripTime;
+ if (maximumInterestRoundTripTime_ < roundTripTime)
+ maximumInterestRoundTripTime_ = roundTripTime;
+ if (trafficPattern_[patternId].minimumInterestRoundTripTime > roundTripTime)
+ trafficPattern_[patternId].minimumInterestRoundTripTime = roundTripTime;
+ if (trafficPattern_[patternId].maximumInterestRoundTripTime < roundTripTime)
+ trafficPattern_[patternId].maximumInterestRoundTripTime = roundTripTime;
+ totalInterestRoundTripTime_ += roundTripTime;
+ trafficPattern_[patternId].totalInterestRoundTripTime += roundTripTime;
+ if (totalInterestSent_ == interestCount_)
+ signalHandler();
+ }
+
+ void
+ onTimeout( ndn::Face &face,
+ const ndn::Interest& interest,
+ int globalReference,
+ int localReference,
+ int patternId)
+ {
+ std::string logLine;
+ logLine = "";
+ logLine += "Interest Timed Out - PatternType="+toString(patternId+1);
+ logLine += ", GlobalID="+toString(globalReference);
+ logLine += ", LocalID="+toString(localReference);
+ logLine += ", Name="+interest.getName().toUri();
+ m_logger.log(logLine, true, false);
+ if (totalInterestSent_ == interestCount_)
+ signalHandler();
+ }
+
+ void
+ generateTraffic( const boost::system::error_code& errorCode,
+ boost::asio::deadline_timer* deadlineTimer )
+ {
+ if ((interestCount_ < 0) || (totalInterestSent_ < interestCount_))
+ {
+ int trafficKey, patternId, cumulativePercentage;
+ std::srand(std::time(0));
+ trafficKey = std::rand() % 100;
+ cumulativePercentage = 0;
+ for (patternId=0; patternId<trafficPattern_.size(); patternId++)
+ {
+ cumulativePercentage += trafficPattern_[patternId].trafficPercentage;
+ if (trafficKey <= cumulativePercentage)
+ {
+ Name interestName(trafficPattern_[patternId].name);
+ if (trafficPattern_[patternId].nameAppendBytes > 0)
+ interestName.append(getRandomByteString(trafficPattern_[patternId].nameAppendBytes));
+ if (trafficPattern_[patternId].nameAppendSequenceNumber >= 0)
+ {
+ interestName.append(toString(trafficPattern_[patternId].nameAppendSequenceNumber));
+ trafficPattern_[patternId].nameAppendSequenceNumber++;
+ }
+ Interest interest(interestName);
+ if (trafficPattern_[patternId].minSuffixComponents >= 0)
+ interest.setMinSuffixComponents(trafficPattern_[patternId].minSuffixComponents);
+ if (trafficPattern_[patternId].maxSuffixComponents >= 0)
+ interest.setMaxSuffixComponents(trafficPattern_[patternId].maxSuffixComponents);
+ Exclude exclude;
+ if (trafficPattern_[patternId].excludeBefore != "" &&
+ trafficPattern_[patternId].excludeAfter != "")
+ {
+ exclude.excludeRange(name::Component(trafficPattern_[patternId].excludeAfter),
+ name::Component(trafficPattern_[patternId].excludeBefore));
+ interest.setExclude(exclude);
+ }
+ else if (trafficPattern_[patternId].excludeBefore != "")
+ {
+ exclude.excludeBefore(name::Component(trafficPattern_[patternId].excludeBefore));
+ interest.setExclude(exclude);
+ }
+ else if (trafficPattern_[patternId].excludeAfter != "")
+ {
+ exclude.excludeAfter(name::Component(trafficPattern_[patternId].excludeAfter));
+ interest.setExclude(exclude);
+ }
+ if (trafficPattern_[patternId].excludeBeforeBytes > 0 &&
+ trafficPattern_[patternId].excludeAfterBytes > 0)
+ {
+ exclude.excludeRange(
+ name::Component(getRandomByteString(trafficPattern_[patternId].excludeAfterBytes)),
+ name::Component(getRandomByteString(trafficPattern_[patternId].excludeBeforeBytes)));
+ interest.setExclude(exclude);
+ }
+ else if (trafficPattern_[patternId].excludeBeforeBytes > 0)
+ {
+ exclude.excludeBefore(
+ name::Component(getRandomByteString(trafficPattern_[patternId].excludeBeforeBytes)));
+ interest.setExclude(exclude);
+ }
+ else if (trafficPattern_[patternId].excludeAfterBytes > 0)
+ {
+ exclude.excludeAfter(
+ name::Component(getRandomByteString(trafficPattern_[patternId].excludeAfterBytes)));
+ interest.setExclude(exclude);
+ }
+
+ if (trafficPattern_[patternId].childSelector >= 0)
+ interest.setChildSelector(trafficPattern_[patternId].childSelector);
+
+ if (trafficPattern_[patternId].mustBeFresh == 0)
+ interest.setMustBeFresh(false);
+ else if (trafficPattern_[patternId].mustBeFresh > 0)
+ interest.setMustBeFresh(true);
+ if (trafficPattern_[patternId].nonceDuplicationPercentage > 0)
+ {
+ int duplicationKey;
+ std::srand(std::time(0));
+ duplicationKey = std::rand() % 100;
+ if (trafficPattern_[patternId].nonceDuplicationPercentage <= duplicationKey)
+ interest.setNonce(getOldNonce());
+ else
+ interest.setNonce(getNewNonce());
+ }
+ else
+ interest.setNonce(getNewNonce());
+ if (trafficPattern_[patternId].scope >= 0)
+ interest.setScope(trafficPattern_[patternId].scope);
+ if (trafficPattern_[patternId].interestLifetime >= 0)
+ interest.setInterestLifetime(
+ time::milliseconds(trafficPattern_[patternId].interestLifetime));
+ else
+ interest.setInterestLifetime(
+ time::milliseconds(getDefaultInterestLifetime()));
+ try {
+ totalInterestSent_++;
+ trafficPattern_[patternId].totalInterestSent++;
+ boost::posix_time::ptime sentTime;
+ sentTime = boost::posix_time::microsec_clock::local_time();
+ face_.expressInterest(interest,
+ bind( &NdnTrafficClient::onData,
+ this, boost::ref(face_),
+ _1, _2, totalInterestSent_,
+ trafficPattern_[patternId].totalInterestSent,
+ patternId,
+ sentTime),
+ bind( &NdnTrafficClient::onTimeout,
+ this, boost::ref(face_),
+ _1, totalInterestSent_,
+ trafficPattern_[patternId].totalInterestSent,
+ patternId));
+ std::string logLine;
+ logLine = "";
+ logLine += "Sending Interest - PatternType="+toString(patternId+1);
+ logLine += ", GlobalID="+toString(totalInterestSent_);
+ logLine += ", LocalID="+toString(trafficPattern_[patternId].totalInterestSent);
+ logLine += ", Name="+interest.getName().toUri();
+ m_logger.log(logLine, true, false);
+ deadlineTimer->expires_at(deadlineTimer->expires_at() +
+ boost::posix_time::millisec(interestInterval_));
+ deadlineTimer->async_wait(bind(&NdnTrafficClient::generateTraffic,
+ this,
+ boost::asio::placeholders::error,
+ deadlineTimer));
+ }
+ catch (std::exception &e) {
+ m_logger.log("ERROR: "+(std::string)e.what(), true, true);
+ }
+ break;
+ }
+ }
+ if (patternId==trafficPattern_.size())
+ {
+ deadlineTimer->expires_at(deadlineTimer->expires_at() +
+ boost::posix_time::millisec(interestInterval_));
+ deadlineTimer->async_wait(bind(&NdnTrafficClient::generateTraffic,
+ this,
+ boost::asio::placeholders::error,
+ deadlineTimer));
+ }
+ }
+ }
+
+ void
+ initialize()
+ {
+ boost::asio::signal_set signalSet(*ioService_, SIGINT, SIGTERM);
+ signalSet.async_wait(bind(&NdnTrafficClient::signalHandler, this));
+ m_logger.initializeLog(instanceId_);
+ initializeTrafficConfiguration();
+ boost::asio::deadline_timer deadlineTimer(*ioService_,
+ boost::posix_time::millisec(interestInterval_));
+ deadlineTimer.async_wait(bind(&NdnTrafficClient::generateTraffic,
+ this,
+ boost::asio::placeholders::error,
+ &deadlineTimer));
+ try {
+ face_.processEvents();
+ }
+ catch(std::exception &e) {
+ m_logger.log("ERROR: "+(std::string)e.what(), true, true);
+ m_logger.shutdownLogger();
+ }
+ }
+
+private:
+
+ KeyChain keyChain_;
+ std::string programName_;
+ std::string instanceId_;
+ int interestInterval_;
+ int interestCount_;
+ Logger m_logger;
+ std::string configurationFile_;
+ ptr_lib::shared_ptr<boost::asio::io_service> ioService_;
+ Face face_;
+ std::vector<InterestTrafficConfiguration> trafficPattern_;
+ std::vector<int> nonceList_;
+ int totalInterestSent_;
+ int totalInterestReceived_;
+ int contentInconsistencies_;
+ double minimumInterestRoundTripTime_;
+ double maximumInterestRoundTripTime_;
+ double totalInterestRoundTripTime_;
+
+};
+
+} // namespace ndn
+
+int main( int argc, char* argv[] )
+{
+ int option;
+ ndn::NdnTrafficClient ndnTrafficClient (argv[0]);
+ while ((option = getopt(argc, argv, "hi:c:")) != -1) {
+ switch (option) {
+ case 'h' :
+ ndnTrafficClient.usage();
+ break;
+ case 'i' :
+ ndnTrafficClient.setInterestInterval(atoi(optarg));
+ break;
+ case 'c' :
+ ndnTrafficClient.setInterestCount(atoi(optarg));
+ break;
+ default :
+ ndnTrafficClient.usage();
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argv[0] == NULL)
+ ndnTrafficClient.usage();
+
+ ndnTrafficClient.setConfigurationFile(argv[0]);
+ ndnTrafficClient.initialize();
+
+ return 0;
+}