tools: nfdc support add command

refs: #1407

Change-Id: I35d7d33fda57a34a0a4abc890a5a6dcbc60804c8
diff --git a/tools/nfdc.cpp b/tools/nfdc.cpp
index a603cd6..08ad859 100644
--- a/tools/nfdc.cpp
+++ b/tools/nfdc.cpp
@@ -34,6 +34,8 @@
     "       -h print usage and exit\n"
     "\n"
     "   COMMAND can be one of following:\n"
+    "       add <name> <faceUri> [<cost>]\n"
+    "           Create a face, and add a nexthop for this face to a FIB entry\n"
     "       add-nexthop <name> <faceId> [<cost>]\n"
     "           Add a nexthop to a FIB entry\n"
     "       remove-nexthop <name> <faceId> \n"
@@ -63,40 +65,48 @@
 }
 
 bool
-Nfdc::dispatch(const std::string& command, const char* commandOptions[], int nOptions)
+Nfdc::dispatch(const std::string& command)
 {
-  if (command == "add-nexthop") {
-    if (nOptions == 2)
-      fibAddNextHop(commandOptions, false);
-    else if (nOptions == 3)
-      fibAddNextHop(commandOptions, true);
+  if (command == "add") {
+    if (m_nOptions == 2)
+      addName();
+    else if (m_nOptions == 3)
+      addName();
+    else
+      return false;
+  }
+  else if (command == "add-nexthop") {
+    if (m_nOptions == 2)
+      fibAddNextHop(false);
+    else if (m_nOptions == 3)
+      fibAddNextHop(true);
     else
       return false;
   }
   else if (command == "remove-nexthop") {
-    if (nOptions != 2)
+    if (m_nOptions != 2)
       return false;
-    fibRemoveNextHop(commandOptions);
+    fibRemoveNextHop();
   }
   else if (command == "create") {
-    if (nOptions != 1)
+    if (m_nOptions != 1)
       return false;
-    faceCreate(commandOptions);
+    faceCreate();
   }
   else if (command == "destroy") {
-    if (nOptions != 1)
+    if (m_nOptions != 1)
       return false;
-    faceDestroy(commandOptions);
+    faceDestroy();
   }
   else if (command == "set-strategy") {
-    if (nOptions != 2)
+    if (m_nOptions != 2)
       return false;
-    strategyChoiceSet(commandOptions);
+    strategyChoiceSet();
   }
   else if (command == "unset-strategy") {
-    if (nOptions != 1)
+    if (m_nOptions != 1)
       return false;
-    strategyChoiceUnset(commandOptions);
+    strategyChoiceUnset();
   }
   else
     usage(m_programName);
@@ -104,45 +114,6 @@
   return true;
 }
 
-void
-Nfdc::fibAddNextHop(const char* commandOptions[], bool hasCost)
-{
-  const std::string& name = commandOptions[0];
-  const int faceId = boost::lexical_cast<int>(commandOptions[1]);
-
-  ControlParameters parameters;
-  parameters
-    .setName(name)
-    .setFaceId(faceId);
-
-  if (hasCost)
-  {
-    const uint64_t cost = boost::lexical_cast<uint64_t>(commandOptions[2]);
-    parameters.setCost(cost);
-  }
-
-  m_controller.start<FibAddNextHopCommand>(
-    parameters,
-    bind(&Nfdc::onSuccess, this, _1, "Nexthop insertion succeeded"),
-    bind(&Nfdc::onError, this, _1, _2, "Nexthop insertion failed"));
-}
-
-void
-Nfdc::fibRemoveNextHop(const char* commandOptions[])
-{
-  const std::string& name = commandOptions[0];
-  const int faceId = boost::lexical_cast<int>(commandOptions[1]);
-
-  ControlParameters parameters;
-  parameters
-    .setName(name)
-    .setFaceId(faceId);
-
-  m_controller.start<FibRemoveNextHopCommand>(
-    parameters,
-    bind(&Nfdc::onSuccess, this, _1, "Nexthop removal succeeded"),
-    bind(&Nfdc::onError, this, _1, _2, "Nexthop removal failed"));
-}
 
 namespace {
 
@@ -158,15 +129,78 @@
 } // anonymous namespace
 
 void
-Nfdc::faceCreate(const char* commandOptions[])
+Nfdc::addName()
 {
-  const std::string& uri = commandOptions[0];
-  if (!isValidUri(uri))
+  if (!isValidUri(m_commandLineArguments[1]))
     throw Error("invalid uri format");
 
   ControlParameters parameters;
   parameters
-    .setUri(uri);
+    .setUri(m_commandLineArguments[1]);
+
+  m_controller.start<FaceCreateCommand>(
+    parameters,
+    bind(&Nfdc::onAddSuccess, this, _1, "nfdc add:Face creation succeeded"),
+    bind(&Nfdc::onError, this, _1, _2, "nfdc add: Face creation failed"));
+
+}
+
+void
+Nfdc::fibAddNextHop(bool hasCost)
+{
+  const std::string& name = m_commandLineArguments[0];
+  const int faceId = boost::lexical_cast<int>(m_commandLineArguments[1]);
+
+  fibAddNextHop(name, faceId, hasCost);
+
+}
+
+void
+Nfdc::fibAddNextHop(const std::string& name, const uint64_t faceId, bool hasCost)
+{
+  ControlParameters parameters;
+  parameters
+    .setName(name)
+    .setFaceId(faceId);
+
+  if (hasCost)
+  {
+    const uint64_t cost = boost::lexical_cast<uint64_t>(m_commandLineArguments[2]);
+    parameters.setCost(cost);
+  }
+
+  m_controller.start<FibAddNextHopCommand>(
+    parameters,
+    bind(&Nfdc::onSuccess, this, _1, "Nexthop insertion succeeded"),
+    bind(&Nfdc::onError, this, _1, _2, "Nexthop insertion failed"));
+}
+
+void
+Nfdc::fibRemoveNextHop()
+{
+  const std::string& name = m_commandLineArguments[0];
+  const int faceId = boost::lexical_cast<int>(m_commandLineArguments[1]);
+
+  ControlParameters parameters;
+  parameters
+    .setName(name)
+    .setFaceId(faceId);
+
+  m_controller.start<FibRemoveNextHopCommand>(
+    parameters,
+    bind(&Nfdc::onSuccess, this, _1, "Nexthop removal succeeded"),
+    bind(&Nfdc::onError, this, _1, _2, "Nexthop removal failed"));
+}
+
+void
+Nfdc::faceCreate()
+{
+  if (!isValidUri(m_commandLineArguments[0]))
+    throw Error("invalid uri format");
+
+  ControlParameters parameters;
+  parameters
+    .setUri(m_commandLineArguments[0]);
 
   m_controller.start<FaceCreateCommand>(
     parameters,
@@ -175,9 +209,9 @@
 }
 
 void
-Nfdc::faceDestroy(const char* commandOptions[])
+Nfdc::faceDestroy()
 {
-  const int faceId = boost::lexical_cast<int>(commandOptions[0]);
+  const int faceId = boost::lexical_cast<int>(m_commandLineArguments[0]);
 
   ControlParameters parameters;
   parameters
@@ -190,10 +224,10 @@
 }
 
 void
-Nfdc::strategyChoiceSet(const char* commandOptions[])
+Nfdc::strategyChoiceSet()
 {
-  const std::string& name = commandOptions[0];
-  const std::string& strategy = commandOptions[1];
+  const std::string& name = m_commandLineArguments[0];
+  const std::string& strategy = m_commandLineArguments[1];
 
   ControlParameters parameters;
   parameters
@@ -207,9 +241,9 @@
 }
 
 void
-Nfdc::strategyChoiceUnset(const char* commandOptions[])
+Nfdc::strategyChoiceUnset()
 {
-  const std::string& name = commandOptions[0];
+  const std::string& name = m_commandLineArguments[0];
 
   ControlParameters parameters;
   parameters
@@ -228,6 +262,18 @@
 }
 
 void
+Nfdc::onAddSuccess(const ControlParameters& parameters, const std::string& message)
+{
+  uint64_t faceId = parameters.getFaceId();
+
+  if (m_nOptions == 2)
+    fibAddNextHop(m_commandLineArguments[0], faceId, false);
+  else if (m_nOptions == 3)
+    fibAddNextHop(m_commandLineArguments[0], faceId, true);
+  else
+    throw Error("invalid number of arguments");
+}
+void
 Nfdc::onError(uint32_t code, const std::string& error, const std::string& message)
 {
   std::ostringstream os;
@@ -244,6 +290,7 @@
   nfdc::Nfdc p(face);
 
   p.m_programName = argv[0];
+
   int opt;
   while ((opt = getopt(argc, argv, "h")) != -1) {
     switch (opt) {
@@ -263,9 +310,9 @@
   }
 
   try {
-    bool isOk = p.dispatch(argv[optind],
-                           const_cast<const char**>(argv + optind + 1),
-                           argc - optind - 1);
+    p.m_commandLineArguments = const_cast<const char**>(argv + optind + 1);
+    p.m_nOptions = argc - optind - 1;
+    bool isOk = p.dispatch(argv[optind]);
     if (!isOk) {
       usage(p.m_programName);
       return 1;
diff --git a/tools/nfdc.hpp b/tools/nfdc.hpp
index ab74e10..b54d12f 100644
--- a/tools/nfdc.hpp
+++ b/tools/nfdc.hpp
@@ -28,13 +28,12 @@
 #include <ndn-cpp-dev/face.hpp>
 #include <ndn-cpp-dev/management/controller.hpp>
 #include <ndn-cpp-dev/management/nfd-controller.hpp>
-#include <vector>
 
 namespace nfdc {
 
 using namespace ndn::nfd;
 
-class Nfdc
+class Nfdc : boost::noncopyable
 {
 public:
   class Error : public std::runtime_error
@@ -53,22 +52,31 @@
   ~Nfdc();
 
   bool
-  dispatch(const std::string& cmd,
-           const char* cmdOptions[],
-           int nOptions);
+  dispatch(const std::string& cmd);
 
   /**
+   * \brief Adds a name to a FIB entry after creating the attaced face.
+   *
+   * Create a new face for the given faceUri and use it when adding the given name to the fib
+   *
+   *
+   * cmd format:
+   *   add name faceUri [cost]
+   *
+   */
+  void
+  addName();
+  /**
    * \brief Adds a nexthop to a FIB entry.
    *
    * If the FIB entry does not exist, it is inserted automatically
    *
    * cmd format:
-   *   name
+   *   name faceId [cost]
    *
-   * \param cmdOptions Add next hop command parameters without leading 'add-nexthop' component
    */
   void
-  fibAddNextHop(const char* cmdOptions[], bool hasCost);
+  fibAddNextHop(bool hasCost);
 
   /**
    * \brief Removes a nexthop from an existing FIB entry
@@ -78,11 +86,9 @@
    * cmd format:
    *   name faceId
    *
-   * \param cmdOptions Remove next hop command parameters without leading
-   *                   'remove-nexthop' component
    */
   void
-  fibRemoveNextHop(const char* cmdOptions[]);
+  fibRemoveNextHop();
 
   /**
    * \brief create new face
@@ -92,10 +98,9 @@
    * cmd format:
    *   uri
    *
-   * \param cmdOptions Create face command parameters without leading 'create' component
    */
   void
-  faceCreate(const char* cmdOptions[]);
+  faceCreate();
 
   /**
    * \brief destroy a face
@@ -103,10 +108,9 @@
    * cmd format:
    *   faceId
    *
-   * \param cmdOptions Destroy face command parameters without leading 'destroy' component
    */
   void
-  faceDestroy(const char* cmdOptions[]);
+  faceDestroy();
 
   /**
    * \brief Set the strategy for a namespace
@@ -115,11 +119,9 @@
    * cmd format:
    *   name strategy
    *
-   * \param cmdOptions Set strategy choice command parameters without leading
-   *                   'set-strategy' component
    */
   void
-  strategyChoiceSet(const char* cmdOptions[]);
+  strategyChoiceSet();
 
   /**
    * \brief Unset the strategy for a namespace
@@ -128,23 +130,33 @@
    * cmd format:
    *   name strategy
    *
-   * \param cmdOptions Unset strategy choice command parameters without leading
-   *                   'unset-strategy' component
    */
   void
-  strategyChoiceUnset(const char* cmdOptions[]);
+  strategyChoiceUnset();
 
 private:
+
   void
   onSuccess(const ControlParameters& parameters,
             const std::string& message);
 
   void
+  onAddSuccess(const ControlParameters& parameters,
+               const std::string& message);
+
+  void
   onError(uint32_t code, const std::string& error, const std::string& message);
 
+  void
+  fibAddNextHop(const std::string& name, const uint64_t faceId, bool hasCost);
+
 public:
   const char* m_programName;
 
+  // command parameters without leading 'cmd' component
+  const char** m_commandLineArguments;
+  int m_nOptions;
+
 private:
   Controller m_controller;
 };