face: consistently use the template method pattern in ProtocolFactory

Change-Id: Ied0bf02cfcdffc7e9b2c28c5452441c01f98ccbc
diff --git a/daemon/face/protocol-factory.hpp b/daemon/face/protocol-factory.hpp
index f3d7807..a3cb625 100644
--- a/daemon/face/protocol-factory.hpp
+++ b/daemon/face/protocol-factory.hpp
@@ -62,7 +62,7 @@
   using CtorParams = ProtocolFactoryCtorParams;
 
   /** \brief Register a protocol factory type
-   *  \tparam S subclass of ProtocolFactory
+   *  \tparam PF subclass of ProtocolFactory
    *  \param id factory identifier
    */
   template<typename PF>
@@ -71,16 +71,16 @@
   {
     Registry& registry = getRegistry();
     BOOST_ASSERT(registry.count(id) == 0);
-    registry[id] = &make_unique<PF, const CtorParams&>;
+    registry[id] = [] (const CtorParams& p) { return make_unique<PF>(p); };
   }
 
   /** \brief Create a protocol factory instance
-   *  \retval nullptr if factory with \p id is not registered
+   *  \retval nullptr if a factory with the given \p id is not registered
    */
   static unique_ptr<ProtocolFactory>
   create(const std::string& id, const CtorParams& params);
 
-  /** \brief Get registered protocol factory ids
+  /** \brief Get all registered protocol factory ids
    */
   static std::set<std::string>
   listRegistered();
@@ -91,44 +91,40 @@
   class Error : public std::runtime_error
   {
   public:
-    explicit
-    Error(const std::string& what)
-      : std::runtime_error(what)
-    {
-    }
+    using std::runtime_error::runtime_error;
   };
 
+  explicit
+  ProtocolFactory(const CtorParams& params);
+
   virtual
-  ~ProtocolFactory() = default;
+  ~ProtocolFactory() = 0;
 
 #ifdef DOXYGEN
-  /** \brief Get id for this ProtocolFactory
+  /** \brief Get id for this protocol factory
    *
    *  face_system.factory-id config section is processed by the protocol factory.
    */
   static const std::string&
-  getId();
+  getId() noexcept;
 #endif
 
-  /** \brief Process face_system subsection that corresponds to this ProtocolFactory type
-   *  \param configSection the configuration section or boost::null to indicate it is omitted
-   *  \param context provides access to data structures and contextual information
-   *  \throw ConfigFile::Error invalid configuration
-   *
-   *  This function updates \p providedSchemes
-   */
-  virtual void
-  processConfig(OptionalConfigSection configSection,
-                FaceSystem::ConfigContext& context) = 0;
-
-  /** \brief Get FaceUri schemes accepted by this ProtocolFactory
+  /** \brief Get FaceUri schemes accepted by this protocol factory
    */
   const std::set<std::string>&
-  getProvidedSchemes()
+  getProvidedSchemes() const
   {
     return providedSchemes;
   }
 
+  /** \brief Process face_system subsection that corresponds to this protocol factory id
+   *  \param configSection the configuration section or boost::none to indicate it is omitted
+   *  \param context provides access to data structures and contextual information
+   *  \throw ConfigFile::Error invalid configuration
+   */
+  void
+  processConfig(OptionalConfigSection configSection, FaceSystem::ConfigContext& context);
+
   /** \brief Encapsulates a face creation request and all its parameters
    *
    *  Parameters are passed as a struct rather than individually, so that a future change in the list
@@ -141,20 +137,16 @@
     FaceParams params;
   };
 
-  /** \brief Try to create a unicast face using the supplied parameters
-   *
-   * \param req request object containing the face creation parameters
-   * \param onCreated callback if face creation succeeds or face already exists; the settings
-   *                  of an existing face are not updated if they differ from the request
-   * \param onFailure callback if face creation fails
+  /** \brief Create a unicast face
+   *  \param req request object containing the face creation parameters
+   *  \param onCreated callback if face creation succeeds or face already exists; the settings
+   *                   of an existing face are not updated if they differ from the request
+   *  \param onFailure callback if face creation fails
    */
-  virtual void
+  void
   createFace(const CreateFaceRequest& req,
              const FaceCreatedCallback& onCreated,
-             const FaceCreationFailedCallback& onFailure) = 0;
-
-  virtual std::vector<shared_ptr<const Channel>>
-  getChannels() const = 0;
+             const FaceCreationFailedCallback& onFailure);
 
   /** \brief Create a netdev-bound face
    *  \param remote remote FaceUri, must be canonical
@@ -168,10 +160,12 @@
   createNetdevBoundFace(const FaceUri& remote,
                         const shared_ptr<const ndn::net::NetworkInterface>& netdev);
 
-protected:
-  explicit
-  ProtocolFactory(const CtorParams& params);
+  /** \brief Get list of open channels (listening + non-listening)
+   */
+  std::vector<shared_ptr<const Channel>>
+  getChannels() const;
 
+protected:
   template<typename ChannelMap>
   static std::vector<shared_ptr<const Channel>>
   getChannelsFromMap(const ChannelMap& channelMap)
@@ -182,10 +176,34 @@
   }
 
 private:
+  /** \brief Process face_system subsection that corresponds to this protocol factory id
+   *  \sa processConfig
+   *
+   *  A subclass should override this method if it supports configuration options in the config
+   *  file, and do all the required processing here. The subclass should throw ConfigFile::Error
+   *  if it encounters unrecognized options or invalid values. It should also update
+   *  \p providedSchemes as needed.
+   *
+   *  The base class implementation does nothing.
+   */
+  virtual void
+  doProcessConfig(OptionalConfigSection configSection, FaceSystem::ConfigContext& context);
+
+  /** \brief Create a unicast face
+   *  \sa createFace
+   *
+   *  The base class implementation always invokes the failure callback with error code 406,
+   *  indicating unicast face creation is not supported.
+   */
+  virtual void
+  doCreateFace(const CreateFaceRequest& req,
+               const FaceCreatedCallback& onCreated,
+               const FaceCreationFailedCallback& onFailure);
+
   /** \brief Create a netdev-bound face
    *  \sa createNetdevBoundFace
    *
-   *  The base class implementation always throws Error indicating netdev-bound faces are not
+   *  The base class implementation always throws Error, indicating netdev-bound faces are not
    *  supported.
    *
    *  A subclass that offers netdev-bound faces should override this method, and also expose
@@ -201,6 +219,14 @@
   doCreateNetdevBoundFace(const FaceUri& remote,
                           const shared_ptr<const ndn::net::NetworkInterface>& netif);
 
+  /** \brief Get list of open channels (listening + non-listening)
+   *  \sa getChannels
+   *
+   *  The base class implementation returns an empty list.
+   */
+  virtual std::vector<shared_ptr<const Channel>>
+  doGetChannels() const;
+
 private: // registry
   using CreateFunc = std::function<unique_ptr<ProtocolFactory>(const CtorParams&)>;
   using Registry = std::map<std::string, CreateFunc>; // indexed by factory id
@@ -209,7 +235,7 @@
   getRegistry();
 
 protected:
-  std::set<std::string> providedSchemes; ///< FaceUri schemes provided by this ProtocolFactory
+  std::set<std::string> providedSchemes; ///< FaceUri schemes provided by this protocol factory
   FaceCreatedCallback addFace; ///< callback when a new face is created
 
   /** \brief NetworkMonitor for listing available network interfaces and monitoring their changes
@@ -223,9 +249,9 @@
 } // namespace face
 } // namespace nfd
 
-/** \brief registers a protocol factory
+/** \brief Registers a protocol factory
  *
- *  This macro should appear once in .cpp of each protocol factory.
+ *  This macro should appear once in the .cpp file of each protocol factory.
  */
 #define NFD_REGISTER_PROTOCOL_FACTORY(PF)                      \
 static class NfdAuto ## PF ## ProtocolFactoryRegistrationClass \