face: LinkService and Transport counters

refs #3177

Change-Id: Idc495c58c3103dae5f01a2b6ebbff47a2c4a5d2b
diff --git a/daemon/face/face-counters.hpp b/daemon/face/face-counters.hpp
index 6dc1d6a..90cf106 100644
--- a/daemon/face/face-counters.hpp
+++ b/daemon/face/face-counters.hpp
@@ -1,12 +1,12 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014,  Regents of the University of California,
- *                      Arizona Board of Regents,
- *                      Colorado State University,
- *                      University Pierre & Marie Curie, Sorbonne University,
- *                      Washington University in St. Louis,
- *                      Beijing Institute of Technology,
- *                      The University of Memphis
+ * Copyright (c) 2014-2015,  Regents of the University of California,
+ *                           Arizona Board of Regents,
+ *                           Colorado State University,
+ *                           University Pierre & Marie Curie, Sorbonne University,
+ *                           Washington University in St. Louis,
+ *                           Beijing Institute of Technology,
+ *                           The University of Memphis.
  *
  * This file is part of NFD (Named Data Networking Forwarding Daemon).
  * See AUTHORS.md for complete list of NFD authors and contributors.
@@ -26,83 +26,10 @@
 #ifndef NFD_DAEMON_FACE_FACE_COUNTERS_HPP
 #define NFD_DAEMON_FACE_FACE_COUNTERS_HPP
 
-#include "common.hpp"
+#include "core/counter.hpp"
 
 namespace nfd {
 
-/** \brief represents a counter of number of packets
- */
-// PacketCounter is noncopyable, because increment should be called on the counter,
-// not a copy of it; it's implicitly convertible to uint64_t to be observed
-class PacketCounter : noncopyable
-{
-public:
-  typedef uint64_t rep;
-
-  PacketCounter()
-    : m_value(0)
-  {
-  }
-
-  operator rep() const
-  {
-    return m_value;
-  }
-
-  PacketCounter&
-  operator++()
-  {
-    ++m_value;
-    return *this;
-  }
-  // postfix ++ operator is not provided because it's not needed
-
-  void
-  set(rep value)
-  {
-    m_value = value;
-  }
-
-private:
-  rep m_value;
-};
-
-/** \brief represents a counter of number of bytes
- */
-// ByteCounter is noncopyable, because increment should be called on the counter,
-// not a copy of it; it's implicitly convertible to uint64_t to be observed
-class ByteCounter : noncopyable
-{
-public:
-  typedef uint64_t rep;
-
-  ByteCounter()
-    : m_value(0)
-  {
-  }
-
-  operator rep() const
-  {
-    return m_value;
-  }
-
-  ByteCounter&
-  operator+=(rep n)
-  {
-    m_value += n;
-    return *this;
-  }
-
-  void
-  set(rep value)
-  {
-    m_value = value;
-  }
-
-private:
-  rep m_value;
-};
-
 /** \brief contains network layer packet counters
  */
 class NetworkLayerCounters : noncopyable
diff --git a/daemon/face/link-service.cpp b/daemon/face/link-service.cpp
index 3f19388..45194dd 100644
--- a/daemon/face/link-service.cpp
+++ b/daemon/face/link-service.cpp
@@ -35,7 +35,7 @@
 LinkService::LinkService()
   : m_face(nullptr)
   , m_transport(nullptr)
-  , m_counters(nullptr)
+  , m_oldCounters(nullptr)
 {
 }
 
@@ -51,7 +51,7 @@
 
   m_face = &face;
   m_transport = &transport;
-  m_counters = &m_face->getMutableCounters();
+  m_oldCounters = &m_face->getMutableCounters();
 }
 
 void
@@ -60,7 +60,8 @@
   BOOST_ASSERT(m_transport != nullptr);
   NFD_LOG_FACE_TRACE(__func__);
 
-  ++m_counters->getNOutInterests();
+  ++this->nOutInterests;
+  ++m_oldCounters->getNOutInterests();
 
   doSendInterest(interest);
 }
@@ -71,7 +72,8 @@
   BOOST_ASSERT(m_transport != nullptr);
   NFD_LOG_FACE_TRACE(__func__);
 
-  ++m_counters->getNOutDatas();
+  ++this->nOutData;
+  ++m_oldCounters->getNOutDatas();
 
   doSendData(data);
 }
@@ -82,7 +84,7 @@
   BOOST_ASSERT(m_transport != nullptr);
   NFD_LOG_FACE_TRACE(__func__);
 
-  // TODO#3177 increment counter
+  ++this->nOutNacks;
 
   doSendNack(nack);
 }
@@ -92,7 +94,8 @@
 {
   NFD_LOG_FACE_TRACE(__func__);
 
-  ++m_counters->getNInInterests();
+  ++this->nInInterests;
+  ++m_oldCounters->getNInInterests();
 
   afterReceiveInterest(interest);
 }
@@ -102,7 +105,8 @@
 {
   NFD_LOG_FACE_TRACE(__func__);
 
-  ++m_counters->getNInDatas();
+  ++this->nInData;
+  ++m_oldCounters->getNInDatas();
 
   afterReceiveData(data);
 }
@@ -112,7 +116,7 @@
 {
   NFD_LOG_FACE_TRACE(__func__);
 
-  // TODO#3177 increment counter
+  ++this->nInNacks;
 
   afterReceiveNack(nack);
 }
diff --git a/daemon/face/link-service.hpp b/daemon/face/link-service.hpp
index 1b7bda8..ba7e72f 100644
--- a/daemon/face/link-service.hpp
+++ b/daemon/face/link-service.hpp
@@ -34,12 +34,49 @@
 
 class LpFace;
 
+/** \brief counters provided by LinkService
+ *  \note The type name 'LinkServiceCounters' is implementation detail.
+ *        Use 'LinkService::Counters' in public API.
+ */
+class LinkServiceCounters
+{
+public:
+  /** \brief count of incoming Interests
+   */
+  PacketCounter nInInterests;
+
+  /** \brief count of outgoing Interests
+   */
+  PacketCounter nOutInterests;
+
+  /** \brief count of incoming Data
+   */
+  PacketCounter nInData;
+
+  /** \brief count of outgoing Data
+   */
+  PacketCounter nOutData;
+
+  /** \brief count of incoming Nacks
+   */
+  PacketCounter nInNacks;
+
+  /** \brief count of outgoing Nacks
+   */
+  PacketCounter nOutNacks;
+};
+
 /** \brief the upper part of an LpFace
  *  \sa LpFace
  */
-class LinkService : noncopyable
+class LinkService : protected virtual LinkServiceCounters, noncopyable
 {
 public:
+  /** \brief counters provided by LinkService
+   */
+  typedef LinkServiceCounters Counters;
+
+public:
   LinkService();
 
   virtual
@@ -66,6 +103,9 @@
   Transport*
   getTransport();
 
+  virtual const Counters&
+  getCounters() const;
+
 public: // upper interface to be used by forwarding
   /** \brief send Interest
    *  \pre setTransport has been called
@@ -97,21 +137,11 @@
    */
   signal::Signal<LinkService, lp::Nack> afterReceiveNack;
 
-private: // upper interface to be overridden in subclass (send path entrypoint)
-  /** \brief performs LinkService specific operations to send an Interest
+public: // lower interface to be invoked by Transport
+  /** \brief performs LinkService specific operations to receive a lower-layer packet
    */
-  virtual void
-  doSendInterest(const Interest& interest) = 0;
-
-  /** \brief performs LinkService specific operations to send a Data
-   */
-  virtual void
-  doSendData(const Data& data) = 0;
-
-  /** \brief performs LinkService specific operations to send a Nack
-   */
-  virtual void
-  doSendNack(const lp::Nack& nack) = 0;
+  void
+  receivePacket(Transport::Packet&& packet);
 
 protected: // upper interface to be invoked in subclass (receive path termination)
   /** \brief delivers received Interest to forwarding
@@ -129,18 +159,28 @@
   void
   receiveNack(const lp::Nack& nack);
 
-public: // lower interface to be invoked by Transport
-  /** \brief performs LinkService specific operations to receive a lower-layer packet
-   */
-  void
-  receivePacket(Transport::Packet&& packet);
-
 protected: // lower interface to be invoked in subclass (send path termination)
   /** \brief sends a lower-layer packet via Transport
    */
   void
   sendPacket(Transport::Packet&& packet);
 
+private: // upper interface to be overridden in subclass (send path entrypoint)
+  /** \brief performs LinkService specific operations to send an Interest
+   */
+  virtual void
+  doSendInterest(const Interest& interest) = 0;
+
+  /** \brief performs LinkService specific operations to send a Data
+   */
+  virtual void
+  doSendData(const Data& data) = 0;
+
+  /** \brief performs LinkService specific operations to send a Nack
+   */
+  virtual void
+  doSendNack(const lp::Nack& nack) = 0;
+
 private: // lower interface to be overridden in subclass
   virtual void
   doReceivePacket(Transport::Packet&& packet) = 0;
@@ -148,7 +188,7 @@
 private:
   LpFace* m_face;
   Transport* m_transport;
-  NetworkLayerCounters* m_counters; // TODO#3177 change into NetCounters
+  NetworkLayerCounters* m_oldCounters; // old counters from LpFaceWrapper
 };
 
 inline const LpFace*
@@ -169,6 +209,12 @@
   return m_transport;
 }
 
+inline const LinkService::Counters&
+LinkService::getCounters() const
+{
+  return *this;
+}
+
 inline void
 LinkService::receivePacket(Transport::Packet&& packet)
 {
diff --git a/daemon/face/transport.cpp b/daemon/face/transport.cpp
index 1b7832e..0c4a4c6 100644
--- a/daemon/face/transport.cpp
+++ b/daemon/face/transport.cpp
@@ -65,7 +65,7 @@
   , m_linkType(ndn::nfd::LINK_TYPE_NONE)
   , m_mtu(MTU_INVALID)
   , m_state(TransportState::UP)
-  , m_counters(nullptr)
+  , m_oldCounters(nullptr)
 {
 }
 
@@ -81,7 +81,7 @@
 
   m_face = &face;
   m_service = &service;
-  m_counters = &m_face->getMutableCounters();
+  m_oldCounters = &m_face->getMutableCounters();
 }
 
 void
@@ -109,8 +109,11 @@
     return;
   }
 
-  // TODO#3177 increment LpPacket counter
-  m_counters->getNOutBytes() += packet.packet.size();
+  if (state == TransportState::UP) {
+    ++this->nOutPackets;
+    this->nOutBytes += packet.packet.size();
+    m_oldCounters->getNOutBytes() += packet.packet.size();
+  }
 
   this->doSend(std::move(packet));
 }
@@ -121,8 +124,9 @@
   BOOST_ASSERT(this->getMtu() == MTU_UNLIMITED ||
                packet.packet.size() <= static_cast<size_t>(this->getMtu()));
 
-  // TODO#3177 increment LpPacket counter
-  m_counters->getNInBytes() += packet.packet.size();
+  ++this->nInPackets;
+  this->nInBytes += packet.packet.size();
+  m_oldCounters->getNInBytes() += packet.packet.size();
 
   m_service->receivePacket(std::move(packet));
 }
diff --git a/daemon/face/transport.hpp b/daemon/face/transport.hpp
index d069a0e..b0d10f4 100644
--- a/daemon/face/transport.hpp
+++ b/daemon/face/transport.hpp
@@ -51,6 +51,46 @@
 std::ostream&
 operator<<(std::ostream& os, TransportState state);
 
+/** \brief counters provided by Transport
+ *  \note The type name 'TransportCounters' is implementation detail.
+ *        Use 'Transport::Counters' in public API.
+ */
+class TransportCounters
+{
+public:
+  /** \brief count of incoming packets
+   *
+   *  A 'packet' typically means a top-level TLV block.
+   *  For a datagram-based transport, an incoming packet that cannot be parsed as TLV
+   *  would not be counted.
+   */
+  PacketCounter nInPackets;
+
+  /** \brief count of outgoing packets
+   *
+   *  A 'packet' typically means a top-level TLV block.
+   *  This counter is incremented only if transport is UP.
+   */
+  PacketCounter nOutPackets;
+
+  /** \brief total incoming bytes
+   *
+   *  This counter includes headers imposed by NFD (such as NDNLP),
+   *  but excludes overhead of underlying protocol (such as IP header).
+   *  For a datagram-based transport, an incoming packet that cannot be parsed as TLV
+   *  would not be counted.
+   */
+  ByteCounter nInBytes;
+
+  /** \brief total outgoing bytes
+   *
+   *  This counter includes headers imposed by NFD (such as NDNLP),
+   *  but excludes overhead of underlying protocol (such as IP header).
+   *  This counter is increased only if transport is UP.
+   */
+  ByteCounter nOutBytes;
+};
+
 /** \brief indicates the transport has no limit on payload size
  */
 const ssize_t MTU_UNLIMITED = -1;
@@ -62,7 +102,7 @@
 /** \brief the lower part of an LpFace
  *  \sa LpFace
  */
-class Transport : noncopyable
+class Transport : protected virtual TransportCounters, noncopyable
 {
 public:
   /** \brief identifies an endpoint on the link
@@ -93,6 +133,10 @@
     EndpointId remoteEndpoint;
   };
 
+  /** \brief counters provided by Transport
+   */
+  typedef TransportCounters Counters;
+
   /** \brief constructor
    *
    *  Transport constructor initializes static properties to invalid values.
@@ -128,6 +172,9 @@
   LinkService*
   getLinkService();
 
+  virtual const Counters&
+  getCounters() const;
+
 public: // upper interface
   /** \brief request the transport to be closed
    *
@@ -270,7 +317,7 @@
   ndn::nfd::LinkType m_linkType;
   ssize_t m_mtu;
   TransportState m_state;
-  LinkLayerCounters* m_counters; // TODO#3177 change into LinkCounters
+  LinkLayerCounters* m_oldCounters; // TODO#3177 change into LinkCounters
 };
 
 inline const LpFace*
@@ -291,6 +338,12 @@
   return m_service;
 }
 
+inline const Transport::Counters&
+Transport::getCounters() const
+{
+  return *this;
+}
+
 inline FaceUri
 Transport::getLocalUri() const
 {
diff --git a/daemon/face/websocket-transport.cpp b/daemon/face/websocket-transport.cpp
index cf3da37..6423330 100644
--- a/daemon/face/websocket-transport.cpp
+++ b/daemon/face/websocket-transport.cpp
@@ -106,6 +106,8 @@
 {
   NFD_LOG_FACE_TRACE(__func__);
 
+  ++this->nOutPings;
+
   websocketpp::lib::error_code error;
   m_server.ping(m_handle, "NFD-WebSocket", error);
   if (error)
@@ -118,6 +120,8 @@
 WebSocketTransport::handlePong()
 {
   NFD_LOG_FACE_TRACE(__func__);
+
+  ++this->nInPongs;
 }
 
 void
diff --git a/daemon/face/websocket-transport.hpp b/daemon/face/websocket-transport.hpp
index 91a99c1..08542c0 100644
--- a/daemon/face/websocket-transport.hpp
+++ b/daemon/face/websocket-transport.hpp
@@ -33,16 +33,39 @@
 namespace nfd {
 namespace face {
 
-/**
- * \brief A Transport that communicates on a WebSocket connection
+/** \brief counters provided by WebSocketTransport
+ *  \note The type name 'WebSocketTransportCounters' is implementation detail.
+ *        Use 'WebSocketTransport::Counters' in public API.
  */
-class WebSocketTransport DECL_FINAL : public Transport
+class WebSocketTransportCounters : public virtual Transport::Counters
 {
 public:
+  /** \brief count of outgoing Pings
+   */
+  PacketCounter nOutPings;
+
+  /** \brief count of incoming Pongs
+   */
+  PacketCounter nInPongs;
+};
+
+/** \brief A Transport that communicates on a WebSocket connection
+ */
+class WebSocketTransport DECL_FINAL : public Transport
+                                    , protected virtual WebSocketTransportCounters
+{
+public:
+  /** \brief counters provided by WebSocketTransport
+   */
+  typedef WebSocketTransportCounters Counters;
+
   WebSocketTransport(websocketpp::connection_hdl hdl,
                      websocket::Server& server,
                      time::milliseconds pingInterval);
 
+  virtual const Counters&
+  getCounters() const DECL_OVERRIDE;
+
   /** \brief Translates a message into a Block
    *         and delivers it to the link service
    */
@@ -82,6 +105,12 @@
   scheduler::ScopedEventId m_pingEventId;
 };
 
+inline const WebSocketTransport::Counters&
+WebSocketTransport::getCounters() const
+{
+  return *this;
+}
+
 } // namespace face
 } // namespace nfd