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;

 }