management: Add support to local control header.

Change-Id: I17e066ddec5d8b72a732cabe1cf1b305af2eb1a2
refs: #1169, #1170
diff --git a/src/encoding/tlv-nfd-control.hpp b/src/encoding/tlv-nfd-control.hpp
index 7c07a31..34ac171 100644
--- a/src/encoding/tlv-nfd-control.hpp
+++ b/src/encoding/tlv-nfd-control.hpp
@@ -28,7 +28,13 @@
 
   // Face Management Protocol
   FaceManagementOptions = 108,
-  Uri                   = 114
+  Uri                   = 114,
+
+  // Local Control Header
+  LocalControlHeader = 109,
+  LocalControlInfo   = 110,
+  IncomingFaceId     = 111,
+  NextHopFaceId      = 112
 };
 
 
diff --git a/src/face.cpp b/src/face.cpp
index f43d077..aef13af 100644
--- a/src/face.cpp
+++ b/src/face.cpp
@@ -17,6 +17,7 @@
 
 #include "management/ndnd-controller.hpp"
 #include "management/nfd-controller.hpp"
+#include "encoding/tlv-nfd-control.hpp"
 
 namespace ndn {
 
@@ -288,12 +289,18 @@
 
 
 void
-Face::onReceiveElement(const Block &block)
+Face::onReceiveElement(const Block &blockFromDaemon)
 {
+  Block block = blockFromDaemon;
+  uint64_t incomingFaceId = std::numeric_limits<uint64_t>::max();
+  if (block.type() == tlv::nfd_control::LocalControlHeader)
+    block = wireDecodeLocalControlHeader(block, incomingFaceId);
+  
   if (block.type() == Tlv::Interest)
     {
       shared_ptr<Interest> interest(new Interest());
       interest->wireDecode(block);
+      interest->setIncomingFaceId(incomingFaceId);
 
       RegisteredPrefixTable::iterator entry = getEntryForRegisteredPrefix(interest->getName());
       if (entry != m_registeredPrefixTable.end()) {
@@ -304,6 +311,7 @@
     {
       shared_ptr<Data> data(new Data());
       data->wireDecode(block);
+      data->setIncomingFaceId(incomingFaceId);
 
       PendingInterestTable::iterator entry = getEntryIndexForExpressedInterest(data->getName());
       if (entry != m_pendingInterestTable.end()) {
@@ -321,6 +329,7 @@
         }
       }
     }
+  // ignore any other type
 }
 
 Face::PendingInterestTable::iterator
@@ -360,4 +369,42 @@
   return longestPrefix;
 }
 
+Block
+Face::wireEncodeLocalControlHeader(const Block& blockWithoutHeader, uint64_t nextHopFaceId)
+{
+  Block localControlHeader = Block(tlv::nfd_control::LocalControlHeader);
+  Block localControlInfo = Block(tlv::nfd_control::LocalControlInfo);
+
+  localControlInfo.push_back
+    (nonNegativeIntegerBlock(tlv::nfd_control::NextHopFaceId, nextHopFaceId));
+
+  localControlHeader.push_back(localControlInfo);
+  localControlHeader.push_back(blockWithoutHeader);
+
+  localControlHeader.encode();
+  return localControlHeader;
+}
+
+Block
+Face::wireDecodeLocalControlHeader(const Block& blockWithHeader, uint64_t& incomingFaceId)
+{
+  blockWithHeader.parse();
+  if (blockWithHeader.elements_size() != 2 ||
+      blockWithHeader.elements_begin()->type() != tlv::nfd_control::LocalControlInfo)
+    {
+      return Block();
+    }
+
+  const Block& localControlInfo = *blockWithHeader.elements_begin();
+  localControlInfo.parse();
+
+  Block::element_const_iterator i = localControlInfo.find(tlv::nfd_control::IncomingFaceId);
+  if (i != localControlInfo.elements_end())
+    {
+      incomingFaceId = readNonNegativeInteger(*i);
+    }
+
+  return *blockWithHeader.elements().rbegin();
+}
+
 } // namespace ndn
diff --git a/src/face.hpp b/src/face.hpp
index 6aac1e0..29f80fd 100644
--- a/src/face.hpp
+++ b/src/face.hpp
@@ -238,11 +238,30 @@
    */
   RegisteredPrefixTable::iterator
   getEntryForRegisteredPrefix(const Name& name);
-
   
   void
   checkPitExpire();
-  
+
+  /**
+   * @brief Encode local control header.
+   *
+   * @param blockWithoutHeader Encoded block of interest or data packet.
+   * @param nextHopFaceId Id of the face from which packet will be sent.
+   * @return The encoded block with local control header.
+   */
+  static Block
+  wireEncodeLocalControlHeader(const Block& blockWithoutHeader, uint64_t nextHopFaceId);
+
+  /**
+   * @brief Decode local control header.
+   *
+   * @param blockWithHeader Encoded block with local control header.
+   * @param incomingFaceId On return, the id of the face from which packet is received.
+   * @return The encoded block of interest or data packet.
+   */
+  static Block
+  wireDecodeLocalControlHeader(const Block& blockWithHeader, uint64_t& incomingFaceId);
+
 private:
   shared_ptr<boost::asio::io_service> m_ioService;
   shared_ptr<boost::asio::io_service::work> m_ioServiceWork; // needed if thread needs to be preserved