face: move isListening()/size() to Channel as pure virtual methods

As a side effect, this ensures that Channel cannot be instantiated.

Change-Id: I875876ddf8fc0fbb04f3e88726c708ece8106702
diff --git a/daemon/face/channel.hpp b/daemon/face/channel.hpp
index 300435c..ae3c583 100644
--- a/daemon/face/channel.hpp
+++ b/daemon/face/channel.hpp
@@ -31,16 +31,14 @@
 namespace nfd {
 namespace face {
 
-/**
- * \brief Prototype for the callback that is invoked when the face
- *        is created (as a response to incoming connection or after
- *        connection is established)
+class Face;
+
+/** \brief Prototype for the callback that is invoked when a face is created
+ *         (in response to an incoming connection or after a connection is established)
  */
 typedef function<void(const shared_ptr<Face>& newFace)> FaceCreatedCallback;
 
-/**
- * \brief Prototype for the callback that is invoked when the face
- *        fails to be created
+/** \brief Prototype for the callback that is invoked when a face fails to be created
  */
 typedef function<void(uint32_t status, const std::string& reason)> FaceCreationFailedCallback;
 
@@ -57,7 +55,20 @@
   ~Channel();
 
   const FaceUri&
-  getUri() const;
+  getUri() const
+  {
+    return m_uri;
+  }
+
+  /** \brief Returns whether the channel is listening
+   */
+  virtual bool
+  isListening() const = 0;
+
+  /** \brief Returns the number of faces in the channel
+   */
+  virtual size_t
+  size() const = 0;
 
 protected:
   void
@@ -67,12 +78,6 @@
   FaceUri m_uri;
 };
 
-inline const FaceUri&
-Channel::getUri() const
-{
-  return m_uri;
-}
-
 /** \brief invokes a callback when the face is closed
  *  \param face the face
  *  \param f the callback to be invoked when the face enters CLOSED state
diff --git a/daemon/face/tcp-channel.cpp b/daemon/face/tcp-channel.cpp
index 5f0f940..978f540 100644
--- a/daemon/face/tcp-channel.cpp
+++ b/daemon/face/tcp-channel.cpp
@@ -70,7 +70,7 @@
                     bool wantLocalFieldsEnabled,
                     const FaceCreatedCallback& onFaceCreated,
                     const FaceCreationFailedCallback& onConnectFailed,
-                    const time::seconds& timeout/* = time::seconds(4)*/)
+                    time::nanoseconds timeout)
 {
   auto it = m_channelFaces.find(remoteEndpoint);
   if (it != m_channelFaces.end()) {
@@ -90,12 +90,6 @@
                                    onFaceCreated, onConnectFailed));
 }
 
-size_t
-TcpChannel::size() const
-{
-  return m_channelFaces.size();
-}
-
 void
 TcpChannel::createFace(ip::tcp::socket&& socket,
                        bool isOnDemand,
diff --git a/daemon/face/tcp-channel.hpp b/daemon/face/tcp-channel.hpp
index 9038f59..400cdf9 100644
--- a/daemon/face/tcp-channel.hpp
+++ b/daemon/face/tcp-channel.hpp
@@ -56,6 +56,18 @@
   explicit
   TcpChannel(const tcp::Endpoint& localEndpoint);
 
+  bool
+  isListening() const override
+  {
+    return m_acceptor.is_open();
+  }
+
+  size_t
+  size() const override
+  {
+    return m_channelFaces.size();
+  }
+
   /**
    * \brief Enable listening on the local endpoint, accept connections,
    *        and create faces when remote host makes a connection
@@ -71,23 +83,14 @@
          int backlog = boost::asio::ip::tcp::acceptor::max_connections);
 
   /**
-   * \brief Create a face by establishing connection to remote endpoint
+   * \brief Create a face by establishing a TCP connection to \p remoteEndpoint
    */
   void
   connect(const tcp::Endpoint& remoteEndpoint,
           bool wantLocalFieldsEnabled,
           const FaceCreatedCallback& onFaceCreated,
           const FaceCreationFailedCallback& onConnectFailed,
-          const time::seconds& timeout = time::seconds(4));
-
-  /**
-   * \brief Get number of faces in the channel
-   */
-  size_t
-  size() const;
-
-  bool
-  isListening() const;
+          time::nanoseconds timeout = time::seconds(4));
 
 private:
   void
@@ -125,12 +128,6 @@
   boost::asio::ip::tcp::socket m_acceptSocket;
 };
 
-inline bool
-TcpChannel::isListening() const
-{
-  return m_acceptor.is_open();
-}
-
 } // namespace face
 } // namespace nfd
 
diff --git a/daemon/face/udp-channel.cpp b/daemon/face/udp-channel.cpp
index 491ad82..d22b23c 100644
--- a/daemon/face/udp-channel.cpp
+++ b/daemon/face/udp-channel.cpp
@@ -44,12 +44,6 @@
   setUri(FaceUri(m_localEndpoint));
 }
 
-size_t
-UdpChannel::size() const
-{
-  return m_channelFaces.size();
-}
-
 void
 UdpChannel::connect(const udp::Endpoint& remoteEndpoint,
                     ndn::nfd::FacePersistency persistency,
diff --git a/daemon/face/udp-channel.hpp b/daemon/face/udp-channel.hpp
index b9b71a8..fe849a6 100644
--- a/daemon/face/udp-channel.hpp
+++ b/daemon/face/udp-channel.hpp
@@ -51,11 +51,17 @@
   UdpChannel(const udp::Endpoint& localEndpoint,
              const time::seconds& timeout);
 
-  /**
-   * \brief Get number of faces in the channel
-   */
+  bool
+  isListening() const override
+  {
+    return m_socket.is_open();
+  }
+
   size_t
-  size() const;
+  size() const override
+  {
+    return m_channelFaces.size();
+  }
 
   /**
    * \brief Create a face by establishing connection to remote endpoint
@@ -84,9 +90,6 @@
   listen(const FaceCreatedCallback& onFaceCreated,
          const FaceCreationFailedCallback& onReceiveFailed);
 
-  bool
-  isListening() const;
-
 private:
   void
   waitForNewPeer(const FaceCreatedCallback& onFaceCreated,
@@ -128,12 +131,6 @@
   uint8_t m_inputBuffer[ndn::MAX_NDN_PACKET_SIZE];
 };
 
-inline bool
-UdpChannel::isListening() const
-{
-  return m_socket.is_open();
-}
-
 } // namespace face
 } // namespace nfd
 
diff --git a/daemon/face/unix-stream-channel.cpp b/daemon/face/unix-stream-channel.cpp
index e09cd98..b253a70 100644
--- a/daemon/face/unix-stream-channel.cpp
+++ b/daemon/face/unix-stream-channel.cpp
@@ -40,6 +40,7 @@
   : m_endpoint(endpoint)
   , m_acceptor(getGlobalIoService())
   , m_socket(getGlobalIoService())
+  , m_size(0)
 {
   setUri(FaceUri(m_endpoint));
 }
@@ -136,6 +137,10 @@
   auto linkService = make_unique<GenericLinkService>();
   auto transport = make_unique<UnixStreamTransport>(std::move(m_socket));
   auto face = make_shared<Face>(std::move(linkService), std::move(transport));
+
+  ++m_size;
+  connectFaceClosedSignal(*face, [this] { --m_size; });
+
   onFaceCreated(face);
 
   // prepare accepting the next connection
diff --git a/daemon/face/unix-stream-channel.hpp b/daemon/face/unix-stream-channel.hpp
index 1916134..8f30db5 100644
--- a/daemon/face/unix-stream-channel.hpp
+++ b/daemon/face/unix-stream-channel.hpp
@@ -48,9 +48,14 @@
   /**
    * \brief UnixStreamChannel-related error
    */
-  struct Error : public std::runtime_error
+  class Error : public std::runtime_error
   {
-    Error(const std::string& what) : std::runtime_error(what) {}
+  public:
+    explicit
+    Error(const std::string& what)
+      : std::runtime_error(what)
+    {
+    }
   };
 
   /**
@@ -64,6 +69,18 @@
 
   ~UnixStreamChannel() override;
 
+  bool
+  isListening() const override
+  {
+    return m_acceptor.is_open();
+  }
+
+  size_t
+  size() const override
+  {
+    return m_size;
+  }
+
   /**
    * \brief Enable listening on the local endpoint, accept connections,
    *        and create faces when a connection is made
@@ -78,9 +95,6 @@
          const FaceCreationFailedCallback& onAcceptFailed,
          int backlog = boost::asio::local::stream_protocol::acceptor::max_connections);
 
-  bool
-  isListening() const;
-
 private:
   void
   accept(const FaceCreatedCallback& onFaceCreated,
@@ -95,14 +109,9 @@
   unix_stream::Endpoint m_endpoint;
   boost::asio::local::stream_protocol::acceptor m_acceptor;
   boost::asio::local::stream_protocol::socket m_socket;
+  size_t m_size;
 };
 
-inline bool
-UnixStreamChannel::isListening() const
-{
-  return m_acceptor.is_open();
-}
-
 } // namespace face
 } // namespace nfd
 
diff --git a/daemon/face/websocket-channel.cpp b/daemon/face/websocket-channel.cpp
index cd0df70..daf362c 100644
--- a/daemon/face/websocket-channel.cpp
+++ b/daemon/face/websocket-channel.cpp
@@ -148,11 +148,5 @@
   m_server.start_accept();
 }
 
-size_t
-WebSocketChannel::size() const
-{
-  return m_channelFaces.size();
-}
-
 } // namespace face
 } // namespace nfd
diff --git a/daemon/face/websocket-channel.hpp b/daemon/face/websocket-channel.hpp
index 99153f7..7da5647 100644
--- a/daemon/face/websocket-channel.hpp
+++ b/daemon/face/websocket-channel.hpp
@@ -53,6 +53,18 @@
   explicit
   WebSocketChannel(const websocket::Endpoint& localEndpoint);
 
+  bool
+  isListening() const override
+  {
+    return m_server.is_listening();
+  }
+
+  size_t
+  size() const override
+  {
+    return m_channelFaces.size();
+  }
+
   /**
    * \brief Enable listening on the local endpoint, accept connections,
    *        and create faces when remote host makes a connection
@@ -62,15 +74,6 @@
   void
   listen(const FaceCreatedCallback& onFaceCreated);
 
-  /**
-   * \brief Get number of faces in the channel
-   */
-  size_t
-  size() const;
-
-  bool
-  isListening() const;
-
 PUBLIC_WITH_TESTS_ELSE_PRIVATE:
   /** \pre listen hasn't been invoked
    */
@@ -110,12 +113,6 @@
   time::milliseconds m_pingInterval;
 };
 
-inline bool
-WebSocketChannel::isListening() const
-{
-  return m_server.is_listening();
-}
-
 } // namespace face
 } // namespace nfd
 
diff --git a/tests/daemon/face/unix-stream-channel.t.cpp b/tests/daemon/face/unix-stream-channel.t.cpp
index 1a356c0..c602f97 100644
--- a/tests/daemon/face/unix-stream-channel.t.cpp
+++ b/tests/daemon/face/unix-stream-channel.t.cpp
@@ -103,13 +103,13 @@
   this->listen();
 
   BOOST_CHECK_EQUAL(listenerChannel->isListening(), true);
-  BOOST_CHECK_EQUAL(listenerFaces.size(), 0);
+  BOOST_CHECK_EQUAL(listenerChannel->size(), 0);
 
   local::stream_protocol::socket client1(g_io);
   this->clientConnect(client1);
 
   BOOST_CHECK_EQUAL(limitedIo.run(2, time::seconds(1)), LimitedIo::EXCEED_OPS);
-  BOOST_CHECK_EQUAL(listenerFaces.size(), 1);
+  BOOST_CHECK_EQUAL(listenerChannel->size(), 1);
 
   local::stream_protocol::socket client2(g_io);
   local::stream_protocol::socket client3(g_io);
@@ -117,6 +117,7 @@
   this->clientConnect(client3);
 
   BOOST_CHECK_EQUAL(limitedIo.run(4, time::seconds(1)), LimitedIo::EXCEED_OPS);
+  BOOST_CHECK_EQUAL(listenerChannel->size(), 3);
   BOOST_CHECK_EQUAL(listenerFaces.size(), 3);
 
   // check face persistency
diff --git a/tests/daemon/mgmt/face-manager.t.cpp b/tests/daemon/mgmt/face-manager.t.cpp
index 8856b0a..41dcb90 100644
--- a/tests/daemon/mgmt/face-manager.t.cpp
+++ b/tests/daemon/mgmt/face-manager.t.cpp
@@ -247,6 +247,18 @@
   {
     setUri(FaceUri(uri));
   }
+
+  bool
+  isListening() const final
+  {
+    return false;
+  }
+
+  size_t
+  size() const final
+  {
+    return 0;
+  }
 };
 
 class TestProtocolFactory : public face::ProtocolFactory