management: Implementing nrd::Controller and introducing new secret
environment option to enable NRD Prefix management protocol

Usage for the secret NFD and NRD environment variables

    export NFD=1
    export NRD=1
    <run app>

or

    NFD=1 NRD=1 <run app>

Change-Id: I874acbdcf7038f4d0fa05c59b34cd46d6ae627b0
diff --git a/src/face.cpp b/src/face.cpp
index bc6d877..919ea5d 100644
--- a/src/face.cpp
+++ b/src/face.cpp
@@ -17,6 +17,7 @@
 
 #include "management/ndnd-controller.hpp"
 #include "management/nfd-controller.hpp"
+#include "management/nrd-controller.hpp"
 
 namespace ndn {
 
@@ -62,7 +63,12 @@
   m_processEventsTimeoutTimer = make_shared<boost::asio::deadline_timer>(boost::ref(*m_ioService));
 
   if (std::getenv("NFD") != 0)
-      m_fwController = make_shared<nfd::Controller>(boost::ref(*this));
+    {
+      if (std::getenv("NRD") != 0)
+        m_fwController = make_shared<nrd::Controller>(boost::ref(*this));
+      else
+        m_fwController = make_shared<nfd::Controller>(boost::ref(*this));
+    }
   else
       m_fwController = make_shared<ndnd::Controller>(boost::ref(*this));
 }
diff --git a/src/management/nrd-controller.cpp b/src/management/nrd-controller.cpp
new file mode 100644
index 0000000..2d5557f
--- /dev/null
+++ b/src/management/nrd-controller.cpp
@@ -0,0 +1,109 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2013 Regents of the University of California.
+ * See COPYING for copyright and distribution information.
+ */
+
+#include "common.hpp"
+#include "../face.hpp"
+
+// NRD
+#include "nrd-controller.hpp"
+#include "nrd-prefix-reg-options.hpp"
+
+// NFD
+#include "nfd-control-response.hpp"
+
+namespace ndn {
+namespace nrd {
+
+Controller::Controller(Face& face)
+  : m_face(face)
+  , m_faceId(0)
+{
+}
+
+void
+Controller::selfRegisterPrefix(const Name& prefixToRegister,
+                               const SuccessCallback& onSuccess,
+                               const FailCallback&    onFail)
+{
+  startCommand("register",
+               PrefixRegOptions()
+                 .setName(prefixToRegister)
+                 .setFaceId(0) // self-registration
+                 .setCost(0),
+               bind(&Controller::recordSelfRegisteredFaceId, this, _1, onSuccess),
+               onFail);
+}
+
+void
+Controller::selfDeregisterPrefix(const Name& prefixToRegister,
+                                 const SuccessCallback& onSuccess,
+                                 const FailCallback&    onFail)
+{
+  if (m_faceId == 0)
+    {
+      if (static_cast<bool>(onFail))
+        onFail("Face ID is not set, should have been set after a successful prefix registration command");
+      return;
+    }
+
+  startCommand("unregister",
+               PrefixRegOptions()
+                 .setName(prefixToRegister)
+                 .setFaceId(m_faceId),
+               bind(onSuccess), onFail);
+}
+
+void
+Controller::startCommand(const std::string& command,
+                         const PrefixRegOptions& options,
+                         const CommandSucceedCallback& onSuccess,
+                         const FailCallback& onFail)
+{
+  Name commandInterestName("/localhost/nrd");
+  commandInterestName
+    .append(command)
+    .append(options.wireEncode());
+
+  Interest commandInterest(commandInterestName);
+  // m_keyChain.sign(commandInterest);
+
+  m_face.expressInterest(commandInterest,
+                         bind(&Controller::processCommandResponse, this, _2,
+                              onSuccess, onFail),
+                         bind(onFail, "Command Interest timed out"));
+}
+
+void
+Controller::recordSelfRegisteredFaceId(const PrefixRegOptions& entry,
+                                       const SuccessCallback& onSuccess)
+{
+  m_faceId = entry.getFaceId();
+  onSuccess();
+}
+
+void
+Controller::processCommandResponse(Data& data,
+                                   const CommandSucceedCallback& onSuccess,
+                                   const FailCallback& onFail)
+{
+  try
+    {
+      nfd::ControlResponse response(data.getContent().blockFromValue());
+      if (response.getCode() != 200)
+        return onFail(response.getText());
+
+      PrefixRegOptions options(response.getBody());
+      return onSuccess(options);
+    }
+  catch(ndn::Tlv::Error& e)
+    {
+      if (static_cast<bool>(onFail))
+        return onFail(e.what());
+    }
+}
+
+} // namespace nrd
+} // namespace ndn
diff --git a/src/management/nrd-controller.hpp b/src/management/nrd-controller.hpp
new file mode 100644
index 0000000..c5bd7bf
--- /dev/null
+++ b/src/management/nrd-controller.hpp
@@ -0,0 +1,64 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/**
+ * Copyright (C) 2014 Regents of the University of California.
+ * See COPYING for copyright and distribution information.
+ */
+
+#ifndef NDN_MANAGEMENT_NFD_CONTROLLER_HPP
+#define NDN_MANAGEMENT_NFD_CONTROLLER_HPP
+
+#include "controller.hpp"
+#include "../security/key-chain.hpp"
+
+namespace ndn {
+namespace nrd {
+
+class PrefixRegOptions;
+
+class Controller : public ndn::Controller
+{
+public:
+  typedef function<void(const PrefixRegOptions&)> CommandSucceedCallback;
+
+  /**
+   * @brief Construct ndnd::Control object
+   */
+  Controller(Face& face);
+
+  virtual void
+  selfRegisterPrefix(const Name& prefixToRegister,
+                     const SuccessCallback& onSuccess,
+                     const FailCallback&    onFail);
+
+  virtual void
+  selfDeregisterPrefix(const Name& prefixToRegister,
+                       const SuccessCallback& onSuccess,
+                       const FailCallback&    onFail);
+
+protected:
+  void
+  startCommand(const std::string& command,
+               const PrefixRegOptions& options,
+               const CommandSucceedCallback& onSuccess,
+               const FailCallback& onFailure);
+
+private:
+  void
+  recordSelfRegisteredFaceId(const PrefixRegOptions& entry,
+                             const SuccessCallback& onSuccess);
+
+  void
+  processCommandResponse(Data& data,
+                         const CommandSucceedCallback& onSuccess,
+                         const FailCallback& onFail);
+
+protected:
+  Face& m_face;
+  KeyChain m_keyChain;
+  uint64_t m_faceId; // internal face ID (needed for prefix de-registration)
+};
+
+} // namespace nrd
+} // namespace ndn
+
+#endif // NDN_MANAGEMENT_NFD_CONTROLLER_HPP