face: increment link layer byte counters in StreamFace and DatagramFace

refs #1766

Change-Id: I69377fa561ae1ee845808aa02ae1b85b1771899e
diff --git a/common.hpp b/common.hpp
index 4b6b141..3b9d2ce 100644
--- a/common.hpp
+++ b/common.hpp
@@ -1,11 +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
+ * 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
  *
  * This file is part of NFD (Named Data Networking Forwarding Daemon).
  * See AUTHORS.md for complete list of NFD authors and contributors.
@@ -20,7 +21,7 @@
  *
  * You should have received a copy of the GNU General Public License along with
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- **/
+ */
 
 #ifndef NFD_COMMON_HPP
 #define NFD_COMMON_HPP
@@ -39,6 +40,7 @@
 #define PROTECTED_WITH_TESTS_ELSE_PRIVATE private
 #endif
 
+#include <cstddef>
 #include <list>
 #include <set>
 #include <queue>
@@ -58,6 +60,8 @@
 
 namespace nfd {
 
+using std::size_t;
+
 using boost::noncopyable;
 using boost::scoped_ptr;
 
diff --git a/daemon/face/datagram-face.hpp b/daemon/face/datagram-face.hpp
index dff2012..d065487 100644
--- a/daemon/face/datagram-face.hpp
+++ b/daemon/face/datagram-face.hpp
@@ -83,7 +83,8 @@
 protected:
   void
   handleSend(const boost::system::error_code& error,
-             const Block& wire);
+             size_t nBytesSent,
+             const Block& payload);
 
   void
   handleReceive(const boost::system::error_code& error,
@@ -129,9 +130,9 @@
 DatagramFace<T, U>::sendInterest(const Interest& interest)
 {
   this->onSendInterest(interest);
-  m_socket->async_send(boost::asio::buffer(interest.wireEncode().wire(),
-                                           interest.wireEncode().size()),
-                       bind(&DatagramFace<T, U>::handleSend, this, _1, interest.wireEncode()));
+  const Block& payload = interest.wireEncode();
+  m_socket->async_send(boost::asio::buffer(payload.wire(), payload.size()),
+                       bind(&DatagramFace<T, U>::handleSend, this, _1, _2, payload));
 
   // anything else should be done here?
 }
@@ -141,9 +142,9 @@
 DatagramFace<T, U>::sendData(const Data& data)
 {
   this->onSendData(data);
-  m_socket->async_send(boost::asio::buffer(data.wireEncode().wire(),
-                                           data.wireEncode().size()),
-                       bind(&DatagramFace<T, U>::handleSend, this, _1, data.wireEncode()));
+  const Block& payload = data.wireEncode();
+  m_socket->async_send(boost::asio::buffer(payload.wire(), payload.size()),
+                       bind(&DatagramFace<T, U>::handleSend, this, _1, _2, payload));
 
   // anything else should be done here?
 }
@@ -151,14 +152,15 @@
 template<class T, class U>
 inline void
 DatagramFace<T, U>::handleSend(const boost::system::error_code& error,
-                               const Block& wire)
+                               size_t nBytesSent,
+                               const Block& payload)
+// 'payload' is unused; it's needed to retain the underlying Buffer
 {
   if (error != 0) {
     if (error == boost::system::errc::operation_canceled) // when socket is closed by someone
       return;
 
-    if (!m_socket->is_open())
-    {
+    if (!m_socket->is_open()) {
       fail("Tunnel closed");
       return;
     }
@@ -170,12 +172,10 @@
 
     closeSocket();
 
-    if (error == boost::asio::error::eof)
-    {
+    if (error == boost::asio::error::eof) {
       fail("Tunnel closed");
     }
-    else
-    {
+    else {
       fail("Send operation failed, closing socket: " +
              error.category().message(error.value()));
     }
@@ -184,8 +184,8 @@
 
   NFD_LOG_TRACE("[id:" << this->getId()
                 << ",uri:" << this->getRemoteUri()
-                << "] Successfully sent: " << wire.size() << " bytes");
-  // do nothing (needed to retain validity of wire memory block
+                << "] Successfully sent: " << nBytesSent << " bytes");
+  this->getMutableCounters().getNOutBytes() += nBytesSent;
 }
 
 template<class T, class U>
@@ -226,8 +226,7 @@
       return;
 
     // this should be unnecessary, but just in case
-    if (!m_socket->is_open())
-    {
+    if (!m_socket->is_open()) {
       fail("Tunnel closed");
       return;
     }
@@ -239,12 +238,10 @@
 
     closeSocket();
 
-    if (error == boost::asio::error::eof)
-    {
+    if (error == boost::asio::error::eof) {
       fail("Tunnel closed");
     }
-    else
-    {
+    else {
       fail("Receive operation failed, closing socket: " +
              error.category().message(error.value()));
     }
@@ -254,6 +251,7 @@
   NFD_LOG_TRACE("[id:" << this->getId()
                 << ",uri:" << this->getRemoteUri()
                 << "] Received: " << nBytesReceived << " bytes");
+  this->getMutableCounters().getNInBytes() += nBytesReceived;
 
   Block element;
   bool isOk = Block::fromBuffer(buffer, nBytesReceived, element);
diff --git a/daemon/face/face.cpp b/daemon/face/face.cpp
index 385f0a9..bbf2a08 100644
--- a/daemon/face/face.cpp
+++ b/daemon/face/face.cpp
@@ -21,7 +21,7 @@
  *
  * You should have received a copy of the GNU General Public License along with
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- **/
+ */
 
 #include "face.hpp"
 #include "face-flags.hpp"
diff --git a/daemon/face/multicast-udp-face.cpp b/daemon/face/multicast-udp-face.cpp
index a69b1c2..34c6cd2 100644
--- a/daemon/face/multicast-udp-face.cpp
+++ b/daemon/face/multicast-udp-face.cpp
@@ -55,7 +55,7 @@
 {
   m_sendSocket->async_send_to(boost::asio::buffer(block.wire(), block.size()),
                               m_multicastGroup,
-                              bind(&MulticastUdpFace::handleSend, this, _1, block));
+                              bind(&MulticastUdpFace::handleSend, this, _1, _2, block));
 }
 
 void
diff --git a/daemon/face/stream-face.hpp b/daemon/face/stream-face.hpp
index ef28c25..8eb7af0 100644
--- a/daemon/face/stream-face.hpp
+++ b/daemon/face/stream-face.hpp
@@ -21,7 +21,7 @@
  *
  * You should have received a copy of the GNU General Public License along with
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- **/
+ */
 
 #ifndef NFD_DAEMON_FACE_STREAM_FACE_HPP
 #define NFD_DAEMON_FACE_STREAM_FACE_HPP
@@ -70,11 +70,11 @@
 
   void
   handleSend(const boost::system::error_code& error,
-             std::size_t nBytesTransferred);
+             size_t nBytesSent);
 
   void
   handleReceive(const boost::system::error_code& error,
-                std::size_t nBytesReceived);
+                size_t nBytesReceived);
 
   void
   keepFaceAliveUntilAllHandlersExecuted(const shared_ptr<Face>& face);
@@ -87,7 +87,7 @@
 
 private:
   uint8_t m_inputBuffer[MAX_NDN_PACKET_SIZE];
-  std::size_t m_inputBufferSize;
+  size_t m_inputBufferSize;
   std::queue<Block> m_sendQueue;
 
   friend struct StreamFaceSenderImpl<Protocol, FaceBase, Interest>;
@@ -257,7 +257,7 @@
 template<class T, class U>
 inline void
 StreamFace<T, U>::handleSend(const boost::system::error_code& error,
-                             size_t nBytesTransferred)
+                             size_t nBytesSent)
 {
   if (error)
     return processErrorCode(error);
@@ -266,7 +266,8 @@
 
   NFD_LOG_TRACE("[id:" << this->getId()
                 << ",uri:" << this->getRemoteUri()
-                << "] Successfully sent: " << nBytesTransferred << " bytes");
+                << "] Successfully sent: " << nBytesSent << " bytes");
+  this->getMutableCounters().getNOutBytes() += nBytesSent;
 
   m_sendQueue.pop();
   if (!m_sendQueue.empty())
@@ -276,7 +277,7 @@
 template<class T, class U>
 inline void
 StreamFace<T, U>::handleReceive(const boost::system::error_code& error,
-                                std::size_t nBytesReceived)
+                                size_t nBytesReceived)
 {
   if (error)
     return processErrorCode(error);
@@ -284,15 +285,15 @@
   NFD_LOG_TRACE("[id:" << this->getId()
                 << ",uri:" << this->getRemoteUri()
                 << "] Received: " << nBytesReceived << " bytes");
+  this->getMutableCounters().getNInBytes() += nBytesReceived;
 
   m_inputBufferSize += nBytesReceived;
-  // do magic
 
-  std::size_t offset = 0;
+  size_t offset = 0;
 
   bool isOk = true;
   Block element;
-  while(m_inputBufferSize - offset > 0)
+  while (m_inputBufferSize - offset > 0)
     {
       isOk = Block::fromBuffer(m_inputBuffer + offset, m_inputBufferSize - offset, element);
       if (!isOk)
diff --git a/daemon/face/udp-channel.cpp b/daemon/face/udp-channel.cpp
index 8d1e780..151f235 100644
--- a/daemon/face/udp-channel.cpp
+++ b/daemon/face/udp-channel.cpp
@@ -1,11 +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
+ * 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
  *
  * This file is part of NFD (Named Data Networking Forwarding Daemon).
  * See AUTHORS.md for complete list of NFD authors and contributors.
@@ -20,7 +21,7 @@
  *
  * You should have received a copy of the GNU General Public License along with
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- **/
+ */
 
 #include "udp-channel.hpp"
 #include "core/global-io.hpp"
@@ -200,7 +201,7 @@
 
 void
 UdpChannel::newPeer(const boost::system::error_code& error,
-                    std::size_t nBytesReceived)
+                    size_t nBytesReceived)
 {
   NFD_LOG_DEBUG("UdpChannel::newPeer from " << m_newRemoteEndpoint);
 
diff --git a/daemon/face/udp-channel.hpp b/daemon/face/udp-channel.hpp
index fed232a..da2b14b 100644
--- a/daemon/face/udp-channel.hpp
+++ b/daemon/face/udp-channel.hpp
@@ -1,11 +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
+ * 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
  *
  * This file is part of NFD (Named Data Networking Forwarding Daemon).
  * See AUTHORS.md for complete list of NFD authors and contributors.
@@ -20,7 +21,7 @@
  *
  * You should have received a copy of the GNU General Public License along with
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- **/
+ */
 
 #ifndef NFD_DAEMON_FACE_UDP_CHANNEL_HPP
 #define NFD_DAEMON_FACE_UDP_CHANNEL_HPP
@@ -124,7 +125,7 @@
    *        associated with any UdpFace
    */
   void
-  newPeer(const boost::system::error_code& error, std::size_t nBytesReceived);
+  newPeer(const boost::system::error_code& error, size_t nBytesReceived);
 
   void
   handleEndpointResolution(const boost::system::error_code& error,
diff --git a/tests/daemon/face/tcp.cpp b/tests/daemon/face/tcp.cpp
index 2861be3..fa527e9 100644
--- a/tests/daemon/face/tcp.cpp
+++ b/tests/daemon/face/tcp.cpp
@@ -261,6 +261,7 @@
   face1->sendInterest(*interest1);
   face1->sendInterest(*interest1);
   face1->sendData    (*data1    );
+  size_t nBytesSent1 = interest1->wireEncode().size() * 3 + data1->wireEncode().size();
   face2->sendInterest(*interest2);
   face2->sendData    (*data2    );
   face2->sendData    (*data2    );
@@ -269,7 +270,6 @@
   BOOST_CHECK_MESSAGE(limitedIo.run(8, time::seconds(10)) == LimitedIo::EXCEED_OPS,
                       "TcpChannel error: cannot send or receive Interest/Data packets");
 
-
   BOOST_REQUIRE_EQUAL(face1_receivedInterests.size(), 1);
   BOOST_REQUIRE_EQUAL(face1_receivedDatas    .size(), 3);
   BOOST_REQUIRE_EQUAL(face2_receivedInterests.size(), 3);
@@ -280,17 +280,22 @@
   BOOST_CHECK_EQUAL(face2_receivedInterests[0].getName(), interest1->getName());
   BOOST_CHECK_EQUAL(face2_receivedDatas    [0].getName(), data1->getName());
 
+  // needed to ensure NOutBytes counters are accurate
+  limitedIo.run(LimitedIo::UNLIMITED_OPS, time::seconds(1));
+
   const FaceCounters& counters1 = face1->getCounters();
   BOOST_CHECK_EQUAL(counters1.getNInInterests() , 1);
   BOOST_CHECK_EQUAL(counters1.getNInDatas()     , 3);
   BOOST_CHECK_EQUAL(counters1.getNOutInterests(), 3);
   BOOST_CHECK_EQUAL(counters1.getNOutDatas()    , 1);
+  BOOST_CHECK_EQUAL(counters1.getNOutBytes(), nBytesSent1);
 
   const FaceCounters& counters2 = face2->getCounters();
   BOOST_CHECK_EQUAL(counters2.getNInInterests() , 3);
   BOOST_CHECK_EQUAL(counters2.getNInDatas()     , 1);
   BOOST_CHECK_EQUAL(counters2.getNOutInterests(), 1);
   BOOST_CHECK_EQUAL(counters2.getNOutDatas()    , 3);
+  BOOST_CHECK_EQUAL(counters2.getNInBytes(), nBytesSent1);
 }
 
 BOOST_FIXTURE_TEST_CASE(EndToEnd6, EndToEndFixture)
diff --git a/tests/daemon/face/udp.cpp b/tests/daemon/face/udp.cpp
index f2d3417..40485ca 100644
--- a/tests/daemon/face/udp.cpp
+++ b/tests/daemon/face/udp.cpp
@@ -379,6 +379,8 @@
   BOOST_CHECK_EQUAL(face2->getRemoteUri().toString(), "udp4://127.0.0.1:20070");
   BOOST_CHECK_EQUAL(face2->getLocalUri().toString(), "udp4://127.0.0.1:20071");
   BOOST_CHECK_EQUAL(face2->isLocal(), false);
+  BOOST_CHECK_EQUAL(face2->getCounters().getNOutBytes(), 0);
+  BOOST_CHECK_EQUAL(face2->getCounters().getNInBytes(), 0);
   // face1 is not created yet
 
   shared_ptr<UdpChannel> channel1 = factory.createChannel("127.0.0.1", "20070");
@@ -410,6 +412,7 @@
   face2->sendData    (data2    );
   face2->sendData    (data2    );
   face2->sendData    (data2    );
+  size_t nBytesSent2 = interest2.wireEncode().size() + data2.wireEncode().size() * 3;
 
   BOOST_CHECK_MESSAGE(limitedIo.run(5,//4 send + 1 listen return
                       time::seconds(4)) == LimitedIo::EXCEED_OPS,
@@ -428,7 +431,6 @@
   BOOST_CHECK_MESSAGE(limitedIo.run(4, time::seconds(4)) == LimitedIo::EXCEED_OPS,
                       "UdpChannel error: cannot send or receive Interest/Data packets");
 
-
   BOOST_REQUIRE_EQUAL(face1_receivedInterests.size(), 1);
   BOOST_REQUIRE_EQUAL(face1_receivedDatas    .size(), 3);
   BOOST_REQUIRE_EQUAL(face2_receivedInterests.size(), 3);
@@ -445,6 +447,7 @@
 
   face2->sendData    (data3    );
   face2->sendInterest(interest3);
+  nBytesSent2 += data3.wireEncode().size() + interest3.wireEncode().size();
 
   BOOST_CHECK_MESSAGE(limitedIo.run(2, time::seconds(1)) == LimitedIo::EXCEED_OPS,
                       "UdpChannel error: cannot send or receive Interest/Data packets");
@@ -460,12 +463,14 @@
   BOOST_CHECK_EQUAL(counters1.getNInDatas()     , 4);
   BOOST_CHECK_EQUAL(counters1.getNOutInterests(), 3);
   BOOST_CHECK_EQUAL(counters1.getNOutDatas()    , 1);
+  BOOST_CHECK_EQUAL(counters1.getNInBytes(), nBytesSent2);
 
   const FaceCounters& counters2 = face2->getCounters();
   BOOST_CHECK_EQUAL(counters2.getNInInterests() , 3);
   BOOST_CHECK_EQUAL(counters2.getNInDatas()     , 1);
   BOOST_CHECK_EQUAL(counters2.getNOutInterests(), 2);
   BOOST_CHECK_EQUAL(counters2.getNOutDatas()    , 4);
+  BOOST_CHECK_EQUAL(counters2.getNOutBytes(), nBytesSent2);
 }
 
 BOOST_FIXTURE_TEST_CASE(EndToEnd6, EndToEndFixture)
diff --git a/tests/daemon/face/unix-stream.cpp b/tests/daemon/face/unix-stream.cpp
index cb48db4..24154ec 100644
--- a/tests/daemon/face/unix-stream.cpp
+++ b/tests/daemon/face/unix-stream.cpp
@@ -213,10 +213,12 @@
   face1->sendInterest(*interest1);
   face1->sendInterest(*interest1);
   face1->sendData    (*data1    );
+  size_t nBytesSent1 = interest1->wireEncode().size() * 3 + data1->wireEncode().size();
   face2->sendInterest(*interest2);
   face2->sendData    (*data2    );
   face2->sendData    (*data2    );
   face2->sendData    (*data2    );
+  size_t nBytesSent2 = interest2->wireEncode().size() + data2->wireEncode().size() * 3;
 
   BOOST_CHECK_MESSAGE(limitedIo.run(8, time::seconds(1)) == LimitedIo::EXCEED_OPS,
                       "UnixStreamChannel error: cannot send or receive Interest/Data packets");
@@ -231,11 +233,16 @@
   BOOST_CHECK_EQUAL(face2_receivedInterests[0].getName(), interest1->getName());
   BOOST_CHECK_EQUAL(face2_receivedDatas    [0].getName(), data1->getName());
 
+  // needed to ensure NOutBytes counters are accurate
+  limitedIo.run(LimitedIo::UNLIMITED_OPS, time::seconds(1));
+
   const FaceCounters& counters1 = face1->getCounters();
   BOOST_CHECK_EQUAL(counters1.getNInInterests() , 1);
   BOOST_CHECK_EQUAL(counters1.getNInDatas()     , 3);
   BOOST_CHECK_EQUAL(counters1.getNOutInterests(), 3);
   BOOST_CHECK_EQUAL(counters1.getNOutDatas()    , 1);
+  BOOST_CHECK_EQUAL(counters1.getNInBytes(), nBytesSent2);
+  BOOST_CHECK_EQUAL(counters1.getNOutBytes(), nBytesSent1);
 
   const FaceCounters& counters2 = face2->getCounters();
   BOOST_CHECK_EQUAL(counters2.getNInInterests() , 3);