management: Fixing regression with ndnd prefix/face registration

The previous commit tried to introduce a cheat to obtain ``ndndid`` from
the name of the returned Data packet, requested using
'/%C1.M.S.localhost/%C1.M.SRV/ndnd/KEY'.  The problem was that the
component in the Data packet contained an extra prefix (%C1.M.K%00),
which should have been stripped out.

Change-Id: I36ef2e566ea155dc86cd13412fc26cf7669dbf24
diff --git a/src/management/ndnd-controller.cpp b/src/management/ndnd-controller.cpp
index a897e27..486a611 100644
--- a/src/management/ndnd-controller.cpp
+++ b/src/management/ndnd-controller.cpp
@@ -63,13 +63,26 @@
 }
 
 
-void 
+void
 Controller::onNdnidFetched(const Interest& interest, Data& data)
 {
   if (data.getName().size() > interest.getName().size())
     {
       m_ndndId = data.getName()[interest.getName().size()];
 
+      if (m_ndndId.value_size() < 6)
+        {
+          for (FilterRequestList::iterator i = m_filterRequests.begin();
+               i != m_filterRequests.end();
+               ++i)
+            {
+              if (static_cast<bool>(i->m_onFailure))
+                i->m_onFailure("Fetched unrecognized NDNID");
+            }
+
+          return;
+        }
+
       for (FilterRequestList::iterator i = m_filterRequests.begin();
            i != m_filterRequests.end();
            ++i)
@@ -110,7 +123,7 @@
   Data data;
   data.setName(Name().appendVersion(ndn::random::generateWord32()));
   data.setContent(entry.wireEncode());
-  
+
   // Create an empty signature, since nobody going to verify it for now
   // @todo In the future, we may require real signatures to do the registration
   SignatureSha256WithRsa signature;
@@ -120,7 +133,7 @@
   // Create an interest where the name has the encoded Data packet.
   Name interestName;
   interestName.append("ndnx");
-  interestName.append(m_ndndId);
+  interestName.append(m_ndndId.value_begin()+6, m_ndndId.value_end());
   interestName.append(entry.getAction());
   interestName.append(data.wireEncode());
 
@@ -143,7 +156,7 @@
   Data data;
   data.setName(Name().appendVersion(random::generateWord32()));
   data.setContent(entry.wireEncode());
-  
+
   // Create an empty signature, since nobody going to verify it for now
   // @todo In the future, we may require real signatures to do the registration
   SignatureSha256WithRsa signature;
@@ -153,7 +166,7 @@
   // Create an interest where the name has the encoded Data packet.
   Name interestName;
   interestName.append("ndnx");
-  interestName.append(m_ndndId);
+  interestName.append(m_ndndId.value_begin()+6, m_ndndId.value_end());
   interestName.append(entry.getAction());
   interestName.append(data.wireEncode());
 
@@ -183,7 +196,7 @@
     }
 
   Block::element_const_iterator val = content.elements_begin();
-  
+
   switch(val->type())
     {
     case Tlv::FaceManagement::FaceInstance:
@@ -229,7 +242,7 @@
     }
 
   Block::element_const_iterator val = content.elements_begin();
-  
+
   switch(val->type())
     {
     case Tlv::FaceManagement::ForwardingEntry:
@@ -247,7 +260,7 @@
         resp.wireDecode(*val);
 
         // std::cerr << "StatusReponse: " << resp << std::endl;
-      
+
         if (static_cast<bool>(onFail))
           onFail(resp.getInfo());
         return;
diff --git a/src/name.hpp b/src/name.hpp
index d58e485..0bfbdba 100644
--- a/src/name.hpp
+++ b/src/name.hpp
@@ -129,6 +129,18 @@
     return *this;
   }
 
+  /**
+   * Append a new component, copying from value of length valueLength.
+   * @return This name so that you can chain calls to append.
+   */
+  template<class InputIterator>
+  Name&
+  append(InputIterator begin, InputIterator end)
+  {
+    m_nameBlock.push_back(Component(begin, end));
+    return *this;
+  }
+
   // /**
   //  * Append a new component, copying from value.
   //  * @return This name so that you can chain calls to append.
diff --git a/tests/test-faces.cpp b/tests/test-faces.cpp
index 498ca73..9fc5860 100644
--- a/tests/test-faces.cpp
+++ b/tests/test-faces.cpp
@@ -5,6 +5,7 @@
 
 #include <boost/test/unit_test.hpp>
 #include "face.hpp"
+#include "util/scheduler.hpp"
 
 using namespace std;
 namespace ndn {
@@ -16,6 +17,9 @@
   FacesFixture()
     : dataCount(0)
     , timeoutCount(0)
+    , regPrefixId(0)
+    , inInterestCount(0)
+    , regFailedCount(0)
   {
   }
   
@@ -32,17 +36,41 @@
   }
 
   void
-  onInterest()
+  onInterest(Face& face)
   {
+    ++inInterestCount;
+
+    face.unsetInterestFilter(regPrefixId);
   }
 
   void
   onRegFailed()
   {
+    ++regFailedCount;
+  }
+
+  void
+  expressInterest(Face& face, const Name& name)
+  {
+    Interest i(name);
+    i.setInterestLifetime(50);
+    face.expressInterest(i,
+                         bind(&FacesFixture::onData, this),
+                         bind(&FacesFixture::onTimeout, this));
+  }
+
+  void
+  terminate(Face& face)
+  {
+    face.shutdown();
   }
 
   uint32_t dataCount;
   uint32_t timeoutCount;
+
+  const RegisteredPrefixId* regPrefixId;
+  uint32_t inInterestCount;
+  uint32_t regFailedCount;
 };
 
 BOOST_FIXTURE_TEST_CASE (Unix, FacesFixture)
@@ -73,8 +101,8 @@
   Face face("localhost");
 
   face.expressInterest(Interest("/%C1.M.S.localhost/%C1.M.SRV/ndnd/KEY", 1000),
-                       ptr_lib::bind(&FacesFixture::onData, this),
-                       ptr_lib::bind(&FacesFixture::onTimeout, this));
+                       bind(&FacesFixture::onData, this),
+                       bind(&FacesFixture::onTimeout, this));
 
   BOOST_REQUIRE_NO_THROW(face.processEvents());
 
@@ -82,8 +110,8 @@
   BOOST_CHECK_EQUAL(timeoutCount, 0);
 
   face.expressInterest(Interest("/localhost/non-existing/data/should/not/exist/anywhere", 50),
-                       ptr_lib::bind(&FacesFixture::onData, this),
-                       ptr_lib::bind(&FacesFixture::onTimeout, this));
+                       bind(&FacesFixture::onData, this),
+                       bind(&FacesFixture::onTimeout, this));
 
   BOOST_REQUIRE_NO_THROW(face.processEvents());
 
@@ -91,6 +119,31 @@
   BOOST_CHECK_EQUAL(timeoutCount, 1);
 }
 
+
+BOOST_FIXTURE_TEST_CASE (SetFilter, FacesFixture)
+{
+  Face face;
+  Face face2(face.ioService());
+  Scheduler scheduler(*face.ioService());
+  scheduler.scheduleEvent(time::seconds(0.3),
+                          bind(&FacesFixture::terminate, this, func_lib::ref(face)));
+  
+  regPrefixId = face.setInterestFilter("/Hello/World",
+                                       bind(&FacesFixture::onInterest, this, func_lib::ref(face)),
+                                       bind(&FacesFixture::onRegFailed, this));
+
+  scheduler.scheduleEvent(time::seconds(0.2),
+                          bind(&FacesFixture::expressInterest, this,
+                               func_lib::ref(face2), Name("/Hello/World/!")));
+  
+  BOOST_REQUIRE_NO_THROW(face.processEvents());
+
+  BOOST_CHECK_EQUAL(regFailedCount, 0);  
+  BOOST_CHECK_EQUAL(inInterestCount, 1);  
+  BOOST_CHECK_EQUAL(timeoutCount, 1);
+  BOOST_CHECK_EQUAL(dataCount, 0);
+}
+
 BOOST_AUTO_TEST_SUITE_END()
 
 } // namespace ndn