face: Allow specifying specific Controller in constructor

This is helpful for applications that needs to either select custom
controller or directly communicate with NFD (e.g., NRD needs that).

Change-Id: I711eb71f7e85a6f8bdbaaad19745f2903bfac487
diff --git a/src/face.cpp b/src/face.cpp
index 919ea5d..aa25e8d 100644
--- a/src/face.cpp
+++ b/src/face.cpp
@@ -24,36 +24,55 @@
 Face::Face()
 {
   construct(shared_ptr<Transport>(new UnixTransport()),
-            make_shared<boost::asio::io_service>());
+            make_shared<boost::asio::io_service>(),
+            shared_ptr<Controller>());
 }
 
-Face::Face(const shared_ptr<boost::asio::io_service> &ioService)
+Face::Face(const shared_ptr<Controller>& controller)
 {
   construct(shared_ptr<Transport>(new UnixTransport()),
-            ioService);
+            make_shared<boost::asio::io_service>(),
+            controller);
 }
 
-Face::Face(const std::string &host, const std::string &port/* = "6363"*/)
+Face::Face(const shared_ptr<boost::asio::io_service>& ioService)
+{
+  construct(shared_ptr<Transport>(new UnixTransport()),
+            ioService,
+            shared_ptr<Controller>());
+}
+
+Face::Face(const std::string& host, const std::string& port/* = "6363"*/)
 {
   construct(shared_ptr<Transport>(new TcpTransport(host, port)),
-            make_shared<boost::asio::io_service>());
+            make_shared<boost::asio::io_service>(),
+            shared_ptr<Controller>());
 }
 
 Face::Face(const shared_ptr<Transport>& transport)
 {
   construct(transport,
-            make_shared<boost::asio::io_service>());
+            make_shared<boost::asio::io_service>(),
+            shared_ptr<Controller>());
 }
 
 Face::Face(const shared_ptr<Transport>& transport,
-           const shared_ptr<boost::asio::io_service> &ioService)
+           const shared_ptr<boost::asio::io_service>& ioService)
 {
-  construct(transport, ioService);
+  construct(transport, ioService, shared_ptr<Controller>());
+}
+
+Face::Face(const shared_ptr<Transport>& transport,
+           const shared_ptr<boost::asio::io_service>& ioService,
+           const shared_ptr<Controller>& controller)
+{
+  construct(transport, ioService, controller);
 }
 
 void
 Face::construct(const shared_ptr<Transport>& transport,
-                const shared_ptr<boost::asio::io_service> &ioService)
+                const shared_ptr<boost::asio::io_service>& ioService,
+                const shared_ptr<Controller>& controller)
 {
   m_pitTimeoutCheckTimerActive = false;
   m_transport = transport;
@@ -62,15 +81,22 @@
   m_pitTimeoutCheckTimer      = make_shared<boost::asio::deadline_timer>(boost::ref(*m_ioService));
   m_processEventsTimeoutTimer = make_shared<boost::asio::deadline_timer>(boost::ref(*m_ioService));
 
-  if (std::getenv("NFD") != 0)
+  if (static_cast<bool>(controller))
     {
-      if (std::getenv("NRD") != 0)
-        m_fwController = make_shared<nrd::Controller>(boost::ref(*this));
-      else
-        m_fwController = make_shared<nfd::Controller>(boost::ref(*this));
+      m_fwController = controller;
     }
   else
-      m_fwController = make_shared<ndnd::Controller>(boost::ref(*this));
+    {
+      if (std::getenv("NFD") != 0)
+        {
+          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));
+    }
 }
 
 
@@ -90,7 +116,7 @@
 
 const PendingInterestId*
 Face::expressInterest(const Name& name,
-                      const Interest &tmpl,
+                      const Interest& tmpl,
                       const OnData& onData, const OnTimeout& onTimeout/* = OnTimeout()*/)
 {
   return expressInterest(Interest(name,
@@ -130,7 +156,7 @@
 }
 
 void
-Face::put(const Data &data)
+Face::put(const Data& data)
 {
   if (!m_transport->isConnected())
     m_transport->connect(*m_ioService,
@@ -148,14 +174,14 @@
 }
 
 void
-Face::removePendingInterest(const PendingInterestId *pendingInterestId)
+Face::removePendingInterest(const PendingInterestId* pendingInterestId)
 {
   m_ioService->post(bind(&Face::asyncRemovePendingInterest, this, pendingInterestId));
 }
 
 
 void
-Face::asyncRemovePendingInterest(const PendingInterestId *pendingInterestId)
+Face::asyncRemovePendingInterest(const PendingInterestId* pendingInterestId)
 {
   m_pendingInterestTable.remove_if(MatchPendingInterestId(pendingInterestId));
 }
@@ -175,13 +201,13 @@
 }
 
 void
-Face::unsetInterestFilter(const RegisteredPrefixId *registeredPrefixId)
+Face::unsetInterestFilter(const RegisteredPrefixId* registeredPrefixId)
 {
   m_ioService->post(bind(&Face::asyncUnsetInterestFilter, this, registeredPrefixId));
 }
 
 void
-Face::asyncUnsetInterestFilter(const RegisteredPrefixId *registeredPrefixId)
+Face::asyncUnsetInterestFilter(const RegisteredPrefixId* registeredPrefixId)
 {
   RegisteredPrefixTable::iterator i = std::find_if(m_registeredPrefixTable.begin(), m_registeredPrefixTable.end(),
                                                    MatchRegisteredPrefixId(registeredPrefixId));
@@ -235,12 +261,12 @@
       m_ioService->run();
       m_ioService->reset(); // so it is possible to run processEvents again (if necessary)
     }
-  catch(Face::ProcessEventsTimeout &)
+  catch(Face::ProcessEventsTimeout&)
     {
       // break
       m_ioService->reset();
     }
-  catch(const std::exception &)
+  catch(const std::exception&)
     {
       m_ioService->reset();
       m_pendingInterestTable.clear();
diff --git a/src/face.hpp b/src/face.hpp
index 3dd0456..895c39e 100644
--- a/src/face.hpp
+++ b/src/face.hpp
@@ -53,7 +53,7 @@
 class Face : noncopyable
 {
 public:
-  struct Error : public std::runtime_error { Error(const std::string &what) : std::runtime_error(what) {} };
+  struct Error : public std::runtime_error { Error(const std::string& what) : std::runtime_error(what) {} };
 
   /**
    * @brief Create a new Face for communication with an NDN Forwarder using the default UnixTransport.
@@ -61,18 +61,26 @@
   Face();
 
   /**
+   * @brief Create face, explicitly selecting which controller to use
+   *
+   * Controller controls the way prefixes are registered with local forwarder.
+   */
+  explicit
+  Face(const shared_ptr<Controller>& controller);
+
+  /**
    * @brief Create a new Face for communication with an NDN Forwarder using the default UnixTransport.
    * @param ioService A shared pointer to boost::io_service object that should control all IO operations
    */
   explicit
-  Face(const ptr_lib::shared_ptr<boost::asio::io_service> &ioService);
-  
+  Face(const shared_ptr<boost::asio::io_service>& ioService);
+
   /**
    * Create a new Face for communication with an NDN hub at host:port using the default TcpTransport.
    * @param host The host of the NDN hub.
    * @param port The port or service name of the NDN hub. If omitted. use 6363.
    */
-  Face(const std::string &host, const std::string &port = "6363");
+  Face(const std::string& host, const std::string& port = "6363");
 
   /**
    * Create a new Face for communication with an NDN hub with the given Transport object and connectionInfo.
@@ -95,7 +103,16 @@
    * </code>
    */
   Face(const shared_ptr<Transport>& transport,
-       const shared_ptr<boost::asio::io_service> &ioService);
+       const shared_ptr<boost::asio::io_service>& ioService);
+
+  /**
+   * @brief Create face, explicitly selecting which controller to use
+   *
+   * Controller controls the way prefixes are registered with local forwarder.
+   */
+  Face(const shared_ptr<Transport>& transport,
+       const shared_ptr<boost::asio::io_service>& ioService,
+       const shared_ptr<Controller>& controller);
   
   /**
    * @brief Express Interest
@@ -124,7 +141,7 @@
    */
   const PendingInterestId*
   expressInterest(const Name& name,
-                  const Interest &tmpl,
+                  const Interest& tmpl,
                   const OnData& onData, const OnTimeout& onTimeout = OnTimeout());
   
   /**
@@ -134,7 +151,7 @@
    * @param pendingInterestId The ID returned from expressInterest.
    */
   void
-  removePendingInterest(const PendingInterestId *pendingInterestId);
+  removePendingInterest(const PendingInterestId* pendingInterestId);
   
   /**
    * Register prefix with the connected NDN hub and call onInterest when a matching interest is received.
@@ -158,7 +175,7 @@
    * @param registeredPrefixId The ID returned from registerPrefix.
    */
   void
-  unsetInterestFilter(const RegisteredPrefixId *registeredPrefixId);
+  unsetInterestFilter(const RegisteredPrefixId* registeredPrefixId);
 
    /**
    * @brief Publish data packet
@@ -167,7 +184,7 @@
    * of the local NDN forwarder
    */
   void
-  put(const Data &data);
+  put(const Data& data);
  
   /**
    * Process any data to receive or call timeout callbacks.
@@ -196,7 +213,9 @@
 
 private:
   void
-  construct(const shared_ptr<Transport>& transport, const shared_ptr<boost::asio::io_service>& ioService);
+  construct(const shared_ptr<Transport>& transport,
+            const shared_ptr<boost::asio::io_service>& ioService,
+            const shared_ptr<Controller>& controller);
   
   struct ProcessEventsTimeout {};
   typedef std::list<shared_ptr<PendingInterest> > PendingInterestTable;