face: process face_system.unix config section in UnixStreamFactory

refs #3904

Change-Id: I8f8772054ece2971758efd0599ef06fd3b778735
diff --git a/daemon/face/face-system.cpp b/daemon/face/face-system.cpp
index 8433a16..b084220 100644
--- a/daemon/face/face-system.cpp
+++ b/daemon/face/face-system.cpp
@@ -51,6 +51,10 @@
 {
   ///\todo #3904 make a registry, and construct instances from registry
   m_factories["tcp"] = make_shared<TcpFactory>();
+
+#ifdef HAVE_UNIX_SOCKETS
+  m_factories["unix"] = make_shared<UnixStreamFactory>();
+#endif // HAVE_UNIX_SOCKETS
 }
 
 std::set<const ProtocolFactory*>
@@ -127,10 +131,7 @@
     ///\todo #3521 nicfaces
 
     ///\todo #3904 process these in protocol factory
-    if (sectionName == "unix") {
-      processSectionUnix(subSection, isDryRun);
-    }
-    else if (sectionName == "udp") {
+    if (sectionName == "udp") {
       processSectionUdp(subSection, isDryRun, context.m_nicList);
     }
     else if (sectionName == "ether") {
@@ -146,45 +147,6 @@
 }
 
 void
-FaceSystem::processSectionUnix(const ConfigSection& configSection, bool isDryRun)
-{
-  // ; the unix section contains settings of Unix stream faces and channels
-  // unix
-  // {
-  //   path /var/run/nfd.sock ; Unix stream listener path
-  // }
-
-#if defined(HAVE_UNIX_SOCKETS)
-  std::string path = "/var/run/nfd.sock";
-
-  for (const auto& i : configSection) {
-    if (i.first == "path") {
-      path = i.second.get_value<std::string>();
-    }
-    else {
-      BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option \"" +
-                                              i.first + "\" in \"unix\" section"));
-    }
-  }
-
-  if (!isDryRun) {
-    if (m_factoryByScheme.count("unix") > 0) {
-      return;
-    }
-
-    auto factory = make_shared<UnixStreamFactory>();
-    m_factoryByScheme.emplace("unix", factory);
-
-    auto channel = factory->createChannel(path);
-    channel->listen(bind(&FaceTable::add, &m_faceTable, _1), nullptr);
-  }
-#else
-  BOOST_THROW_EXCEPTION(ConfigFile::Error("NFD was compiled without Unix sockets support, "
-                                          "cannot process \"unix\" section"));
-#endif // HAVE_UNIX_SOCKETS
-}
-
-void
 FaceSystem::processSectionUdp(const ConfigSection& configSection, bool isDryRun,
                               const std::vector<NetworkInterfaceInfo>& nicList)
 {
diff --git a/daemon/face/face-system.hpp b/daemon/face/face-system.hpp
index 48e3ea2..f5d26d3 100644
--- a/daemon/face/face-system.hpp
+++ b/daemon/face/face-system.hpp
@@ -99,9 +99,6 @@
                 const std::string& filename);
 
   void
-  processSectionUnix(const ConfigSection& configSection, bool isDryRun);
-
-  void
   processSectionUdp(const ConfigSection& configSection, bool isDryRun,
                     const std::vector<NetworkInterfaceInfo>& nicList);
 
diff --git a/daemon/face/unix-stream-factory.cpp b/daemon/face/unix-stream-factory.cpp
index bfbab44..b800b7c 100644
--- a/daemon/face/unix-stream-factory.cpp
+++ b/daemon/face/unix-stream-factory.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2016,  Regents of the University of California,
+ * Copyright (c) 2014-2017,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -24,10 +24,62 @@
  */
 
 #include "unix-stream-factory.hpp"
+#include "core/logger.hpp"
 
-#include <boost/filesystem.hpp> // for canonical()
+#include <boost/filesystem.hpp>
 
 namespace nfd {
+namespace face {
+
+NFD_LOG_INIT("UnixStreamFactory");
+
+void
+UnixStreamFactory::processConfig(OptionalConfigSection configSection,
+                                 FaceSystem::ConfigContext& context)
+{
+  // unix
+  // {
+  //   path /var/run/nfd.sock
+  // }
+
+  if (!configSection) {
+    if (!context.isDryRun && !m_channels.empty()) {
+      NFD_LOG_WARN("Cannot disable unix channel after initialization");
+    }
+    return;
+  }
+
+  std::string path = "/var/run/nfd.sock";
+
+  for (const auto& pair : *configSection) {
+    const std::string& key = pair.first;
+    const ConfigSection& value = pair.second;
+
+    if (key == "path") {
+      path = value.get_value<std::string>();
+    }
+    else {
+      BOOST_THROW_EXCEPTION(ConfigFile::Error("Unrecognized option face_system.unix." + key));
+    }
+  }
+
+  if (!context.isDryRun) {
+    auto channel = this->createChannel(path);
+    if (!channel->isListening()) {
+      channel->listen(context.addFace, nullptr);
+    }
+  }
+}
+
+void
+UnixStreamFactory::createFace(const FaceUri& uri,
+                              ndn::nfd::FacePersistency persistency,
+                              bool wantLocalFieldsEnabled,
+                              const FaceCreatedCallback& onCreated,
+                              const FaceCreationFailedCallback& onFailure)
+{
+  onFailure(406, "Unsupported protocol");
+}
 
 shared_ptr<UnixStreamChannel>
 UnixStreamFactory::createChannel(const std::string& unixSocketPath)
@@ -45,26 +97,10 @@
   return channel;
 }
 
-void
-UnixStreamFactory::createFace(const FaceUri& uri,
-                              ndn::nfd::FacePersistency persistency,
-                              bool wantLocalFieldsEnabled,
-                              const FaceCreatedCallback& onCreated,
-                              const FaceCreationFailedCallback& onFailure)
-{
-  onFailure(406, "Unsupported protocol");
-}
-
 std::vector<shared_ptr<const Channel>>
 UnixStreamFactory::getChannels() const
 {
-  std::vector<shared_ptr<const Channel>> channels;
-  channels.reserve(m_channels.size());
-
-  for (const auto& i : m_channels)
-    channels.push_back(i.second);
-
-  return channels;
+  return getChannelsFromMap(m_channels);
 }
 
 shared_ptr<UnixStreamChannel>
@@ -77,4 +113,5 @@
     return nullptr;
 }
 
+} // namespace face
 } // namespace nfd
diff --git a/daemon/face/unix-stream-factory.hpp b/daemon/face/unix-stream-factory.hpp
index 07a8317..82d7e6e 100644
--- a/daemon/face/unix-stream-factory.hpp
+++ b/daemon/face/unix-stream-factory.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2016,  Regents of the University of California,
+ * Copyright (c) 2014-2017,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -30,10 +30,26 @@
 #include "unix-stream-channel.hpp"
 
 namespace nfd {
+namespace face {
 
+/** \brief protocol factory for stream-oriented Unix sockets
+ */
 class UnixStreamFactory : public ProtocolFactory
 {
 public:
+  /** \brief process face_system.unix config section
+   */
+  void
+  processConfig(OptionalConfigSection configSection,
+                FaceSystem::ConfigContext& context) override;
+
+  void
+  createFace(const FaceUri& uri,
+             ndn::nfd::FacePersistency persistency,
+             bool wantLocalFieldsEnabled,
+             const FaceCreatedCallback& onCreated,
+             const FaceCreationFailedCallback& onFailure) override;
+
   /**
    * \brief Create stream-oriented Unix channel using specified socket path
    *
@@ -47,15 +63,7 @@
   shared_ptr<UnixStreamChannel>
   createChannel(const std::string& unixSocketPath);
 
-public: // from ProtocolFactory
-  virtual void
-  createFace(const FaceUri& uri,
-             ndn::nfd::FacePersistency persistency,
-             bool wantLocalFieldsEnabled,
-             const FaceCreatedCallback& onCreated,
-             const FaceCreationFailedCallback& onFailure) override;
-
-  virtual std::vector<shared_ptr<const Channel>>
+  std::vector<shared_ptr<const Channel>>
   getChannels() const override;
 
 private:
@@ -72,6 +80,7 @@
   std::map<unix_stream::Endpoint, shared_ptr<UnixStreamChannel>> m_channels;
 };
 
+} // namespace face
 } // namespace nfd
 
 #endif // NFD_DAEMON_FACE_UNIX_STREAM_FACTORY_HPP