face: Incrementing Face counters

Change-Id: Ia1d7917bb52cf01ab2ff304638bc9f6cbdb2626f
Refs: #1178
diff --git a/daemon/face/datagram-face.hpp b/daemon/face/datagram-face.hpp
index 78a4a12..e7798b1 100644
--- a/daemon/face/datagram-face.hpp
+++ b/daemon/face/datagram-face.hpp
@@ -84,6 +84,7 @@
 inline void
 DatagramFace<T>::sendInterest(const Interest& interest)
 {
+  this->onSendInterest(interest);
   m_socket->async_send(boost::asio::buffer(interest.wireEncode().wire(),
                                            interest.wireEncode().size()),
                        bind(&DatagramFace<T>::handleSend, this, _1, interest.wireEncode()));
@@ -95,6 +96,7 @@
 inline void
 DatagramFace<T>::sendData(const Data& data)
 {
+  this->onSendData(data);
   m_socket->async_send(boost::asio::buffer(data.wireEncode().wire(),
                                            data.wireEncode().size()),
                        bind(&DatagramFace<T>::handleSend, this, _1, data.wireEncode()));
@@ -162,6 +164,7 @@
 DatagramFace<T>::handleReceive(const boost::system::error_code& error,
                                size_t nBytesReceived)
 {
+  NFD_LOG_DEBUG("handleReceive: " << nBytesReceived);
   receiveDatagram(m_inputBuffer, nBytesReceived, error);
   m_socket->async_receive(boost::asio::buffer(m_inputBuffer, MAX_NDN_PACKET_SIZE), 0,
                           bind(&DatagramFace<T>::handleReceive, this, _1, _2));
diff --git a/daemon/face/ethernet-face.cpp b/daemon/face/ethernet-face.cpp
index f98a3da..f279a8f 100644
--- a/daemon/face/ethernet-face.cpp
+++ b/daemon/face/ethernet-face.cpp
@@ -79,12 +79,14 @@
 void
 EthernetFace::sendInterest(const Interest& interest)
 {
+  onSendInterest(interest);
   sendPacket(interest.wireEncode());
 }
 
 void
 EthernetFace::sendData(const Data& data)
 {
+  onSendData(data);
   sendPacket(data.wireEncode());
 }
 
diff --git a/daemon/face/face-counter.cpp b/daemon/face/face-counter.cpp
deleted file mode 100644
index 3597ff1..0000000
--- a/daemon/face/face-counter.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (C) 2014 Named Data Networking Project
- * See COPYING for copyright and distribution information.
- */
-
-#include "face-counter.hpp"
-
-namespace nfd {
-
-FaceCounters::FaceCounters()
-  : m_inInterest(0)
-  , m_inData(0)
-  , m_outInterest(0)
-  , m_outData(0)
-{
-}
-
-} //namespace nfd
diff --git a/daemon/face/face-counter.hpp b/daemon/face/face-counter.hpp
index e5809eb..ba3b98e 100644
--- a/daemon/face/face-counter.hpp
+++ b/daemon/face/face-counter.hpp
@@ -13,13 +13,15 @@
 
 /** \class FaceCounter
  *  \brief represents a counter on face
+ *
+ *  \todo This class should be noncopyable
  */
 typedef uint64_t FaceCounter;
 
 
 /** \brief contains counters on face
  */
-class FaceCounters
+class FaceCounters : noncopyable
 {
 public:
   FaceCounters();
@@ -59,6 +61,14 @@
   FaceCounter m_outData;
 };
 
+inline
+FaceCounters::FaceCounters()
+  : m_inInterest(0)
+  , m_inData(0)
+  , m_outInterest(0)
+  , m_outData(0)
+{
+}
 
 inline const FaceCounter&
 FaceCounters::getInInterest() const
diff --git a/daemon/face/face.cpp b/daemon/face/face.cpp
index 7268ee4..1fb1109 100644
--- a/daemon/face/face.cpp
+++ b/daemon/face/face.cpp
@@ -11,11 +11,22 @@
 
 NFD_LOG_INIT("Face")
 
+template<class Packet>
+static inline void
+increaseCounter(const Packet& packet, FaceCounter& counter)
+{
+  ++counter;
+}
+
 Face::Face(const FaceUri& uri, bool isLocal)
   : m_id(INVALID_FACEID)
   , m_isLocal(isLocal)
   , m_uri(uri)
 {
+  onReceiveInterest += bind(&increaseCounter<Interest>, _1, boost::ref(m_counters.getInInterest()));
+  onReceiveData     += bind(&increaseCounter<Data>,     _1, boost::ref(m_counters.getInData()));
+  onSendInterest    += bind(&increaseCounter<Interest>, _1, boost::ref(m_counters.getOutInterest()));
+  onSendData        += bind(&increaseCounter<Data>,     _1, boost::ref(m_counters.getOutData()));
 }
 
 Face::~Face()
diff --git a/daemon/face/face.hpp b/daemon/face/face.hpp
index 893a253..1efcb35 100644
--- a/daemon/face/face.hpp
+++ b/daemon/face/face.hpp
@@ -51,6 +51,12 @@
   /// fires when a Data is received
   EventEmitter<Data> onReceiveData;
 
+  /// fires when an Interest is sent out
+  EventEmitter<Interest> onSendInterest;
+
+  /// fires when a Data is sent out
+  EventEmitter<Data> onSendData;
+
   /// fires when face disconnects or fails to perform properly
   EventEmitter<std::string/*reason*/> onFail;
 
diff --git a/daemon/face/multicast-udp-face.cpp b/daemon/face/multicast-udp-face.cpp
index e56c147..49146ac 100644
--- a/daemon/face/multicast-udp-face.cpp
+++ b/daemon/face/multicast-udp-face.cpp
@@ -28,6 +28,8 @@
 void
 MulticastUdpFace::sendInterest(const Interest& interest)
 {
+  onSendInterest(interest);
+
   NFD_LOG_DEBUG("Sending interest");
   m_socket->async_send_to(boost::asio::buffer(interest.wireEncode().wire(),
                                               interest.wireEncode().size()),
@@ -40,6 +42,10 @@
 void
 MulticastUdpFace::sendData(const Data& data)
 {
+  /// \todo After this method implements duplicate suppression, onSendData event should
+  ///       be triggered only when data is actually sent out
+  onSendData(data);
+
   NFD_LOG_DEBUG("Sending data");
   m_socket->async_send_to(boost::asio::buffer(data.wireEncode().wire(),
                                            data.wireEncode().size()),
diff --git a/daemon/face/stream-face.hpp b/daemon/face/stream-face.hpp
index 8a0f960..a623665 100644
--- a/daemon/face/stream-face.hpp
+++ b/daemon/face/stream-face.hpp
@@ -166,6 +166,7 @@
 inline void
 StreamFace<T, U>::sendInterest(const Interest& interest)
 {
+  this->onSendInterest(interest);
   StreamFaceSenderImpl<T, U, Interest>::send(*this, interest);
 }
 
@@ -173,6 +174,7 @@
 inline void
 StreamFace<T, U>::sendData(const Data& data)
 {
+  this->onSendData(data);
   StreamFaceSenderImpl<T, U, Data>::send(*this, data);
 }
 
diff --git a/daemon/face/udp-face.cpp b/daemon/face/udp-face.cpp
index dc516a7..ac8e797 100644
--- a/daemon/face/udp-face.cpp
+++ b/daemon/face/udp-face.cpp
@@ -20,6 +20,7 @@
                             std::size_t nBytesReceived,
                             const boost::system::error_code& error)
 {
+  NFD_LOG_DEBUG("handleFirstReceive");
   //checking if the received message size is too big.
   //This check is redundant, since in the actual implementation a packet
   //cannot be bigger than MAX_NDN_PACKET_SIZE
diff --git a/daemon/fw/strategy.hpp b/daemon/fw/strategy.hpp
index 0844eb2..e4df864 100644
--- a/daemon/fw/strategy.hpp
+++ b/daemon/fw/strategy.hpp
@@ -95,7 +95,7 @@
   /// send Interest to outFace
   VIRTUAL_WITH_TESTS void
   sendInterest(shared_ptr<pit::Entry> pitEntry,
-                    shared_ptr<Face> outFace);
+               shared_ptr<Face> outFace);
 
   /** \brief decide that a pending Interest cannot be forwarded
    *
diff --git a/daemon/mgmt/internal-face.cpp b/daemon/mgmt/internal-face.cpp
index f7e5018..5552d02 100644
--- a/daemon/mgmt/internal-face.cpp
+++ b/daemon/mgmt/internal-face.cpp
@@ -18,6 +18,8 @@
 void
 InternalFace::sendInterest(const Interest& interest)
 {
+  onSendInterest(interest);
+
   if (m_interestFilters.size() == 0)
     {
       NFD_LOG_DEBUG("no Interest filters to match against");
@@ -90,6 +92,7 @@
 void
 InternalFace::sendData(const Data& data)
 {
+  onSendData(data);
 }
 
 void
diff --git a/tests/face/dummy-face.hpp b/tests/face/dummy-face.hpp
index e64a162..a28a1bb 100644
--- a/tests/face/dummy-face.hpp
+++ b/tests/face/dummy-face.hpp
@@ -28,6 +28,7 @@
   virtual void
   sendInterest(const Interest& interest)
   {
+    this->onSendInterest(interest);
     m_sentInterests.push_back(interest);
     this->afterSend();
   }
@@ -35,6 +36,7 @@
   virtual void
   sendData(const Data& data)
   {
+    this->onSendData(data);
     m_sentDatas.push_back(data);
     this->afterSend();
   }
diff --git a/tests/face/tcp.cpp b/tests/face/tcp.cpp
index 47c3b5b..332e28c 100644
--- a/tests/face/tcp.cpp
+++ b/tests/face/tcp.cpp
@@ -208,23 +208,39 @@
   data2.setSignature(fakeSignature);
 
   m_face1->sendInterest(interest1);
+  m_face1->sendInterest(interest1);
+  m_face1->sendInterest(interest1);
   m_face1->sendData    (data1    );
   m_face2->sendInterest(interest2);
   m_face2->sendData    (data2    );
+  m_face2->sendData    (data2    );
+  m_face2->sendData    (data2    );
 
-  BOOST_CHECK_MESSAGE(m_limitedIo.run(4, time::seconds(10)) == LimitedIo::EXCEED_OPS,
+  BOOST_CHECK_MESSAGE(m_limitedIo.run(8, time::seconds(10)) == LimitedIo::EXCEED_OPS,
                       "TcpChannel error: cannot send or receive Interest/Data packets");
 
 
   BOOST_REQUIRE_EQUAL(m_face1_receivedInterests.size(), 1);
-  BOOST_REQUIRE_EQUAL(m_face1_receivedDatas    .size(), 1);
-  BOOST_REQUIRE_EQUAL(m_face2_receivedInterests.size(), 1);
+  BOOST_REQUIRE_EQUAL(m_face1_receivedDatas    .size(), 3);
+  BOOST_REQUIRE_EQUAL(m_face2_receivedInterests.size(), 3);
   BOOST_REQUIRE_EQUAL(m_face2_receivedDatas    .size(), 1);
 
   BOOST_CHECK_EQUAL(m_face1_receivedInterests[0].getName(), interest2.getName());
   BOOST_CHECK_EQUAL(m_face1_receivedDatas    [0].getName(), data2.getName());
   BOOST_CHECK_EQUAL(m_face2_receivedInterests[0].getName(), interest1.getName());
   BOOST_CHECK_EQUAL(m_face2_receivedDatas    [0].getName(), data1.getName());
+
+  const FaceCounters& counters1 = m_face1->getCounters();
+  BOOST_CHECK_EQUAL(counters1.getInInterest() , 1);
+  BOOST_CHECK_EQUAL(counters1.getInData()     , 3);
+  BOOST_CHECK_EQUAL(counters1.getOutInterest(), 3);
+  BOOST_CHECK_EQUAL(counters1.getOutData()    , 1);
+
+  const FaceCounters& counters2 = m_face2->getCounters();
+  BOOST_CHECK_EQUAL(counters2.getInInterest() , 3);
+  BOOST_CHECK_EQUAL(counters2.getInData()     , 1);
+  BOOST_CHECK_EQUAL(counters2.getOutInterest(), 1);
+  BOOST_CHECK_EQUAL(counters2.getOutData()    , 3);
 }
 
 BOOST_FIXTURE_TEST_CASE(EndToEnd6, EndToEndFixture)
diff --git a/tests/face/udp.cpp b/tests/face/udp.cpp
index f6ed53b..bab2f2b 100644
--- a/tests/face/udp.cpp
+++ b/tests/face/udp.cpp
@@ -411,6 +411,18 @@
 
   BOOST_CHECK_EQUAL(m_face1_receivedInterests[1].getName(), interest3.getName());
   BOOST_CHECK_EQUAL(m_face1_receivedDatas    [3].getName(), data3.getName());
+
+  const FaceCounters& counters1 = m_face1->getCounters();
+  BOOST_CHECK_EQUAL(counters1.getInInterest() , 2);
+  BOOST_CHECK_EQUAL(counters1.getInData()     , 4);
+  BOOST_CHECK_EQUAL(counters1.getOutInterest(), 3);
+  BOOST_CHECK_EQUAL(counters1.getOutData()    , 1);
+
+  const FaceCounters& counters2 = m_face2->getCounters();
+  BOOST_CHECK_EQUAL(counters2.getInInterest() , 3);
+  BOOST_CHECK_EQUAL(counters2.getInData()     , 1);
+  BOOST_CHECK_EQUAL(counters2.getOutInterest(), 2);
+  BOOST_CHECK_EQUAL(counters2.getOutData()    , 4);
 }
 
 BOOST_FIXTURE_TEST_CASE(EndToEnd6, EndToEndFixture)
diff --git a/tests/face/unix-stream.cpp b/tests/face/unix-stream.cpp
index 09ee905..285b85f 100644
--- a/tests/face/unix-stream.cpp
+++ b/tests/face/unix-stream.cpp
@@ -174,22 +174,38 @@
   data2.setSignature(fakeSignature);
 
   m_face1->sendInterest(interest1);
+  m_face1->sendInterest(interest1);
+  m_face1->sendInterest(interest1);
   m_face1->sendData    (data1    );
   m_face2->sendInterest(interest2);
   m_face2->sendData    (data2    );
+  m_face2->sendData    (data2    );
+  m_face2->sendData    (data2    );
 
-  BOOST_CHECK_MESSAGE(m_limitedIo.run(4, time::seconds(1)) == LimitedIo::EXCEED_OPS,
+  BOOST_CHECK_MESSAGE(m_limitedIo.run(8, time::seconds(1)) == LimitedIo::EXCEED_OPS,
                       "UnixStreamChannel error: cannot send or receive Interest/Data packets");
 
   BOOST_REQUIRE_EQUAL(m_face1_receivedInterests.size(), 1);
-  BOOST_REQUIRE_EQUAL(m_face1_receivedDatas    .size(), 1);
-  BOOST_REQUIRE_EQUAL(m_face2_receivedInterests.size(), 1);
+  BOOST_REQUIRE_EQUAL(m_face1_receivedDatas    .size(), 3);
+  BOOST_REQUIRE_EQUAL(m_face2_receivedInterests.size(), 3);
   BOOST_REQUIRE_EQUAL(m_face2_receivedDatas    .size(), 1);
 
   BOOST_CHECK_EQUAL(m_face1_receivedInterests[0].getName(), interest2.getName());
   BOOST_CHECK_EQUAL(m_face1_receivedDatas    [0].getName(), data2.getName());
   BOOST_CHECK_EQUAL(m_face2_receivedInterests[0].getName(), interest1.getName());
   BOOST_CHECK_EQUAL(m_face2_receivedDatas    [0].getName(), data1.getName());
+
+  const FaceCounters& counters1 = m_face1->getCounters();
+  BOOST_CHECK_EQUAL(counters1.getInInterest() , 1);
+  BOOST_CHECK_EQUAL(counters1.getInData()     , 3);
+  BOOST_CHECK_EQUAL(counters1.getOutInterest(), 3);
+  BOOST_CHECK_EQUAL(counters1.getOutData()    , 1);
+
+  const FaceCounters& counters2 = m_face2->getCounters();
+  BOOST_CHECK_EQUAL(counters2.getInInterest() , 3);
+  BOOST_CHECK_EQUAL(counters2.getInData()     , 1);
+  BOOST_CHECK_EQUAL(counters2.getOutInterest(), 1);
+  BOOST_CHECK_EQUAL(counters2.getOutData()    , 3);
 }
 
 BOOST_FIXTURE_TEST_CASE(MultipleAccepts, EndToEndFixture)