nfdc: Added name registration and FaceUri support

refs: #1416
refs: #1515

Change-Id: I2f899182bcdad69366fe88f90ff3e7eae9068d26
diff --git a/tools/nfdc.cpp b/tools/nfdc.cpp
index 08ad859..6e14023 100644
--- a/tools/nfdc.cpp
+++ b/tools/nfdc.cpp
@@ -6,6 +6,7 @@
  *                     University Pierre & Marie Curie, Sorbonne University,
  *                     Washington University in St. Louis,
  *                     Beijing Institute of Technology
+ *                     The University of Memphis
  *
  * This file is part of NFD (Named Data Networking Forwarding Daemon).
  * See AUTHORS.md for complete list of NFD authors and contributors.
@@ -30,21 +31,27 @@
 void
 usage(const char* programName)
 {
-  std::cout << "Usage:\n" << programName  << " [-h] COMMAND\n"
+  std::cout << "Usage:\n" << programName  << " [-h] COMMAND [<Command Options>]\n"
     "       -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"
+    "   COMMAND can be one of the following:\n"
+    "       add-nexthop [-c <cost>] <name> <faceId | faceUri>\n"
     "           Add a nexthop to a FIB entry\n"
+    "           -c: specify cost\n"
     "       remove-nexthop <name> <faceId> \n"
     "           Remove a nexthop from a FIB entry\n"
-    "       create <uri> \n"
+    "       register [-I] [-C] [-c cost] name <faceId | faceUri>\n"
+    "           register name to the given faceId or faceUri\n"
+    "           -I: unset CHILD_INHERIT flag\n"
+    "           -C: set CAPTURE flag\n"
+    "           -c: specify cost\n"
+    "       unregister name <faceId>\n"
+    "           unregister name from the given faceId\n"
+    "       create <faceUri> \n"
     "           Create a face in one of the following formats:\n"
     "           UDP unicast:    udp[4|6]://<remote-IP-or-host>[:<remote-port>]\n"
     "           TCP:            tcp[4|6]://<remote-IP-or-host>[:<remote-port>] \n"
-    "       destroy <faceId> \n"
+    "       destroy <faceId | faceUri> \n"
     "           Destroy a face\n"
     "       set-strategy <name> <strategy> \n"
     "           Set the strategy for a namespace \n"
@@ -56,7 +63,9 @@
 namespace nfdc {
 
 Nfdc::Nfdc(ndn::Face& face)
-  : m_controller(face)
+  : m_flags(ROUTE_FLAG_CHILD_INHERIT)
+  , m_cost(0)
+  , m_controller(face)
 {
 }
 
@@ -67,27 +76,26 @@
 bool
 Nfdc::dispatch(const std::string& command)
 {
-  if (command == "add") {
-    if (m_nOptions == 2)
-      addName();
-    else if (m_nOptions == 3)
-      addName();
-    else
+  if (command == "add-nexthop") {
+    if (m_nOptions != 2)
       return false;
-  }
-  else if (command == "add-nexthop") {
-    if (m_nOptions == 2)
-      fibAddNextHop(false);
-    else if (m_nOptions == 3)
-      fibAddNextHop(true);
-    else
-      return false;
+    fibAddNextHop();
   }
   else if (command == "remove-nexthop") {
     if (m_nOptions != 2)
       return false;
     fibRemoveNextHop();
   }
+  else if (command == "register") {
+    if (m_nOptions != 2)
+      return false;
+    ribRegisterPrefix();
+  }
+  else if (command == "unregister") {
+    if (m_nOptions != 2)
+      return false;
+    ribUnregisterPrefix();
+  }
   else if (command == "create") {
     if (m_nOptions != 1)
       return false;
@@ -114,7 +122,6 @@
   return true;
 }
 
-
 namespace {
 
 inline bool
@@ -129,67 +136,147 @@
 } // anonymous namespace
 
 void
-Nfdc::addName()
+Nfdc::fibAddNextHop()
 {
-  if (!isValidUri(m_commandLineArguments[1]))
-    throw Error("invalid uri format");
-
+  m_name = m_commandLineArguments[0];
   ControlParameters parameters;
   parameters
-    .setUri(m_commandLineArguments[1]);
+    .setName(m_name)
+    .setCost(m_cost);
 
-  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);
+  if (!isValidUri(m_commandLineArguments[1])) {
+    try { //So the uri is not valid, may be a faceId is provided.
+      m_faceId = boost::lexical_cast<int>(m_commandLineArguments[1]);
+    }
+    catch (const std::exception& e) {
+      std::cerr << "No valid faceUri or faceId is provided"<< std::endl;
+      return;
+    }
+    parameters.setFaceId(m_faceId);
+    fibAddNextHop(parameters);
   }
+  else {
+    ControlParameters faceParameters;
+    faceParameters.setUri(m_commandLineArguments[1]);
 
-  m_controller.start<FibAddNextHopCommand>(
-    parameters,
-    bind(&Nfdc::onSuccess, this, _1, "Nexthop insertion succeeded"),
-    bind(&Nfdc::onError, this, _1, _2, "Nexthop insertion failed"));
+    m_controller.start<FaceCreateCommand>(faceParameters,
+                                          bind(&Nfdc::fibAddNextHop, this, _1),
+                                          bind(&Nfdc::onError, this, _1, _2,
+                                               "Face creation failed"));
+  }
+}
+
+void
+Nfdc::fibAddNextHop(const ControlParameters& faceCreateResult)
+{
+  ControlParameters ribParameters;
+  ribParameters
+    .setName(m_name)
+    .setCost(m_cost)
+    .setFaceId(faceCreateResult.getFaceId());
+
+  m_controller.start<FibAddNextHopCommand>(ribParameters,
+                                           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]);
+  m_name = m_commandLineArguments[0];
+  try {
+    m_faceId = boost::lexical_cast<int>(m_commandLineArguments[1]);
+  }
+  catch (const std::exception& e) {
+    std::cerr << "No valid faceUri or faceId is provided"<< std::endl;
+    return;
+  }
 
   ControlParameters parameters;
   parameters
-    .setName(name)
-    .setFaceId(faceId);
+    .setName(m_name)
+    .setFaceId(m_faceId);
 
-  m_controller.start<FibRemoveNextHopCommand>(
-    parameters,
-    bind(&Nfdc::onSuccess, this, _1, "Nexthop removal succeeded"),
-    bind(&Nfdc::onError, this, _1, _2, "Nexthop removal failed"));
+  m_controller.start<FibRemoveNextHopCommand>(parameters,
+                                              bind(&Nfdc::onSuccess, this, _1,
+                                                   "Nexthop removal succeeded"),
+                                              bind(&Nfdc::onError, this, _1, _2,
+                                                   "Nexthop removal failed"));
+}
+
+void
+Nfdc::ribRegisterPrefix()
+{
+  m_name = m_commandLineArguments[0];
+  ControlParameters parameters;
+  parameters
+    .setName(m_name)
+    .setCost(m_cost)
+    .setFlags(m_flags);
+
+  if (!isValidUri(m_commandLineArguments[1])) {
+    try { //So the uri is not valid, may be a faceId is provided.
+      m_faceId = boost::lexical_cast<int>(m_commandLineArguments[1]);
+    }
+    catch (const std::exception& e) {
+      std::cerr << "No valid faceUri or faceId is provided"<< std::endl;
+      return;
+    }
+    parameters.setFaceId(m_faceId);
+    ribRegisterPrefix(parameters);
+  }
+  else {
+    ControlParameters faceParameters;
+    faceParameters.setUri(m_commandLineArguments[1]);
+
+    m_controller.start<FaceCreateCommand>(faceParameters,
+                                          bind(&Nfdc::ribRegisterPrefix, this, _1),
+                                          bind(&Nfdc::onError, this, _1, _2,
+                                               "Face creation failed"));
+  }
+}
+
+void
+Nfdc::ribRegisterPrefix(const ControlParameters& faceCreateResult)
+{
+  ControlParameters ribParameters;
+  ribParameters
+    .setName(m_name)
+    .setCost(m_cost)
+    .setFlags(m_flags)
+    .setFaceId(faceCreateResult.getFaceId());
+
+  m_controller.start<RibRegisterCommand>(ribParameters,
+                                         bind(&Nfdc::onSuccess, this, _1,
+                                                "Successful in name registration"),
+                                         bind(&Nfdc::onError, this, _1, _2,
+                                                "Failed in name registration"));
+}
+
+void
+Nfdc::ribUnregisterPrefix()
+{
+  m_name = m_commandLineArguments[0];
+  try {
+    m_faceId = boost::lexical_cast<int>(m_commandLineArguments[1]);
+  }
+  catch (const std::exception& e) {
+    std::cerr << "No valid faceUri or faceId is provided"<< std::endl;
+    return;
+  }
+
+  ControlParameters parameters;
+  parameters
+    .setName(m_name)
+    .setFaceId(m_faceId);
+
+  m_controller.start<RibUnregisterCommand>(parameters,
+                                           bind(&Nfdc::onSuccess, this, _1,
+                                                "Successful in unregistering name"),
+                                           bind(&Nfdc::onError, this, _1, _2,
+                                                "Failed in unregistering name"));
 }
 
 void
@@ -199,28 +286,51 @@
     throw Error("invalid uri format");
 
   ControlParameters parameters;
-  parameters
-    .setUri(m_commandLineArguments[0]);
+  parameters.setUri(m_commandLineArguments[0]);
 
-  m_controller.start<FaceCreateCommand>(
-    parameters,
-    bind(&Nfdc::onSuccess, this, _1, "Face creation succeeded"),
-    bind(&Nfdc::onError, this, _1, _2, "Face creation failed"));
+  m_controller.start<FaceCreateCommand>(parameters,
+                                        bind(&Nfdc::onSuccess, this, _1,
+                                             "Face creation succeeded"),
+                                        bind(&Nfdc::onError, this, _1, _2,
+                                             "Face creation failed"));
 }
 
 void
 Nfdc::faceDestroy()
 {
-  const int faceId = boost::lexical_cast<int>(m_commandLineArguments[0]);
-
   ControlParameters parameters;
-  parameters
-    .setFaceId(faceId);
+  if (!isValidUri(m_commandLineArguments[0])) {
+    try { //So the uri is not valid, may be a faceId is provided.
+      m_faceId = boost::lexical_cast<int>(m_commandLineArguments[0]);
+    }
+    catch (const std::exception& e) {
+      std::cerr << "No valid faceUri or faceId is provided" << std::endl;
+      return;
+    }
+    parameters.setFaceId(m_faceId);
+    faceDestroy(parameters);
+  }
+  else{
+    ControlParameters faceParameters;
+    faceParameters.setUri(m_commandLineArguments[0]);
+    m_controller.start<FaceCreateCommand>(faceParameters,
+                                          bind(&Nfdc::faceDestroy, this, _1),
+                                          bind(&Nfdc::onError, this, _1, _2,
+                                               "Face destroy failed"));
+  }
+}
 
-  m_controller.start<FaceDestroyCommand>(
-    parameters,
-    bind(&Nfdc::onSuccess, this, _1, "Face destroy succeeded"),
-    bind(&Nfdc::onError, this, _1, _2, "Face destroy failed"));
+void
+Nfdc::faceDestroy(const ControlParameters& faceCreateResult)
+{
+  ControlParameters faceParameters;
+  faceParameters.setFaceId(faceCreateResult.getFaceId());
+
+  m_controller.start<FaceDestroyCommand>(faceParameters,
+                                         bind(&Nfdc::onSuccess, this, _1,
+                                              "Face destroy succeeded"),
+                                         bind(&Nfdc::onError, this, _1, _2,
+                                              "Face destroy failed"));
 }
 
 void
@@ -234,10 +344,11 @@
     .setName(name)
     .setStrategy(strategy);
 
-  m_controller.start<StrategyChoiceSetCommand>(
-    parameters,
-    bind(&Nfdc::onSuccess, this, _1, "Successfully set strategy choice"),
-    bind(&Nfdc::onError, this, _1, _2, "Failed to set strategy choice"));
+  m_controller.start<StrategyChoiceSetCommand>(parameters,
+                                               bind(&Nfdc::onSuccess, this, _1,
+                                                    "Successfully set strategy choice"),
+                                               bind(&Nfdc::onError, this, _1, _2,
+                                                    "Failed to set strategy choice"));
 }
 
 void
@@ -246,34 +357,22 @@
   const std::string& name = m_commandLineArguments[0];
 
   ControlParameters parameters;
-  parameters
-    .setName(name);
+  parameters.setName(name);
 
-  m_controller.start<StrategyChoiceUnsetCommand>(
-    parameters,
-    bind(&Nfdc::onSuccess, this, _1, "Successfully unset strategy choice"),
-    bind(&Nfdc::onError, this, _1, _2, "Failed to unset strategy choice"));
+  m_controller.start<StrategyChoiceUnsetCommand>(parameters,
+                                                 bind(&Nfdc::onSuccess, this, _1,
+                                                      "Successfully unset strategy choice"),
+                                                 bind(&Nfdc::onError, this, _1, _2,
+                                                      "Failed to unset strategy choice"));
 }
 
 void
-Nfdc::onSuccess(const ControlParameters& parameters, const std::string& message)
+Nfdc::onSuccess(const ControlParameters& commandSuccessResult, const std::string& message)
 {
-  std::cout << message << ": " << parameters << std::endl;
+  std::cout << message << ": " << commandSuccessResult << std::endl;
 }
 
 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;
@@ -281,6 +380,8 @@
   throw Error(os.str());
 }
 
+
+
 } // namespace nfdc
 
 int
@@ -291,16 +392,42 @@
 
   p.m_programName = argv[0];
 
-  int opt;
-  while ((opt = getopt(argc, argv, "h")) != -1) {
-    switch (opt) {
-      case 'h':
-        usage(p.m_programName);
-        return 0;
+  if (argc < 2) {
+    usage(p.m_programName);
+    return 0;
+  }
 
-      default:
-        usage(p.m_programName);
+  if (!strcmp(argv[1], "-h")) {
+    usage(p.m_programName);
+    return 0;
+  }
+
+
+  int opt;
+  //start reading options from 2nd argument i.e. Command
+  optind=2;
+  while ((opt = getopt(argc, argv, "ICc:")) != -1) {
+    switch (opt) {
+    case 'I':
+      p.m_flags =  p.m_flags & ~(nfdc::ROUTE_FLAG_CHILD_INHERIT);
+      break;
+
+    case 'C':
+      p.m_flags =  p.m_flags | nfdc::ROUTE_FLAG_CAPTURE;
+      break;
+
+    case 'c':
+      try {
+        p.m_cost =  boost::lexical_cast<int>(optarg);
+      }
+      catch (const std::exception& e) {
+        std::cerr << "Error: cost must be in integer format" << std::endl;
         return 1;
+      }
+      break;
+    default:
+      usage(p.m_programName);
+      return 1;
     }
   }
 
@@ -310,14 +437,15 @@
   }
 
   try {
-    p.m_commandLineArguments = const_cast<const char**>(argv + optind + 1);
-    p.m_nOptions = argc - optind - 1;
-    bool isOk = p.dispatch(argv[optind]);
+    p.m_commandLineArguments = const_cast<const char**>(argv + optind);
+    p.m_nOptions = argc - optind;
+
+    //argv[1] points to the command, so pass it to the dispatch
+    bool isOk = p.dispatch(argv[1]);
     if (!isOk) {
       usage(p.m_programName);
       return 1;
     }
-
     face.processEvents();
   }
   catch (const std::exception& e) {