face: Fix a serious bug with incoming interests processing

There was an error in logic of matching incoming interests to the
registered prefix table.  There was actually no matching at all, only
search for the longest prefix.

Change-Id: I701655eb4f488938838df78fcb6730968bb1bbbf
diff --git a/src/face.cpp b/src/face.cpp
index fc064f1..0a967e3 100644
--- a/src/face.cpp
+++ b/src/face.cpp
@@ -61,7 +61,7 @@
 
   pitTimeoutCheckTimer_      = make_shared<boost::asio::deadline_timer>(boost::ref(*ioService_));
   processEventsTimeoutTimer_ = make_shared<boost::asio::deadline_timer>(boost::ref(*ioService_));
-  
+
   if (nfdMode)
       m_fwController = make_shared<nfd::Controller>(boost::ref(*this));
   else
@@ -77,9 +77,9 @@
                         bind(&Face::onReceiveElement, this, _1));
 
   shared_ptr<const Interest> interestToExpress(new Interest(interest));
-  
+
   ioService_->post(bind(&Face::asyncExpressInterest, this, interestToExpress, onData, onTimeout));
-  
+
   return reinterpret_cast<const PendingInterestId*>(interestToExpress.get());
 }
 
@@ -114,7 +114,7 @@
     pitTimeoutCheckTimer_->async_wait(bind(&Face::checkPitExpire, this));
   }
 }
-    
+
 void
 Face::put(const Data &data)
 {
@@ -149,7 +149,7 @@
   m_fwController->selfRegisterPrefix(prefixToRegister->getPrefix(),
                                      bind(&RegisteredPrefixTable::push_back, &registeredPrefixTable_, prefixToRegister),
                                      bind(onSetInterestFilterFailed, prefixToRegister->getPrefix(), _1));
-  
+
   return reinterpret_cast<const RegisteredPrefixId*>(prefixToRegister.get());
 }
 
@@ -163,7 +163,7 @@
 Face::asyncUnsetInterestFilter(const RegisteredPrefixId *registeredPrefixId)
 {
   RegisteredPrefixTable::iterator i = std::find_if(registeredPrefixTable_.begin(), registeredPrefixTable_.end(),
-                                                   MatchRegisteredPrefixId(registeredPrefixId));  
+                                                   MatchRegisteredPrefixId(registeredPrefixId));
   if (i != registeredPrefixTable_.end())
     {
       m_fwController->selfDeregisterPrefix((*i)->getPrefix(),
@@ -188,7 +188,7 @@
     }
 }
 
-void 
+void
 Face::processEvents(Milliseconds timeout/* = 0 */, bool keepThread/* = false*/)
 {
   try
@@ -205,12 +205,12 @@
           processEventsTimeoutTimer_->expires_from_now(boost::posix_time::milliseconds(timeout));
           processEventsTimeoutTimer_->async_wait(&fireProcessEventsTimeout);
         }
-      
+
       if (keepThread) {
         // work will ensure that ioService_ is running until work object exists
         ioServiceWork_ = make_shared<boost::asio::io_service::work>(boost::ref(*ioService_));
       }
-          
+
       ioService_->run();
       ioService_->reset(); // so it is possible to run processEvents again (if necessary)
     }
@@ -228,7 +228,7 @@
     }
 }
 
-void 
+void
 Face::shutdown()
 {
   pendingInterestTable_.clear();
@@ -271,7 +271,7 @@
 
   if (!pendingInterestTable_.empty()) {
     pitTimeoutCheckTimerActive_ = true;
-    
+
     pitTimeoutCheckTimer_->expires_from_now(boost::posix_time::milliseconds(100));
     pitTimeoutCheckTimer_->async_wait(bind(&Face::checkPitExpire, this));
   }
@@ -288,14 +288,14 @@
 }
 
 
-void 
+void
 Face::onReceiveElement(const Block &block)
 {
   if (block.type() == Tlv::Interest)
     {
       shared_ptr<Interest> interest(new Interest());
       interest->wireDecode(block);
-    
+
       RegisteredPrefixTable::iterator entry = getEntryForRegisteredPrefix(interest->getName());
       if (entry != registeredPrefixTable_.end()) {
         (*entry)->getOnInterest()((*entry)->getPrefix(), *interest);
@@ -324,7 +324,7 @@
     }
 }
 
-Face::PendingInterestTable::iterator 
+Face::PendingInterestTable::iterator
 Face::getEntryIndexForExpressedInterest(const Name& name)
 {
   for (PendingInterestTable::iterator i = pendingInterestTable_.begin ();
@@ -338,7 +338,7 @@
 
   return pendingInterestTable_.end();
 }
-  
+
 Face::RegisteredPrefixTable::iterator
 Face::getEntryForRegisteredPrefix(const Name& name)
 {
@@ -348,10 +348,14 @@
        i != registeredPrefixTable_.end();
        ++i)
     {
-      if (longestPrefix == registeredPrefixTable_.end() ||
-          (*i)->getPrefix().size() > (*longestPrefix)->getPrefix().size())
+      if ((*i)->getPrefix().isPrefixOf(name))
         {
-          longestPrefix = i;
+
+          if (longestPrefix == registeredPrefixTable_.end() ||
+              (*i)->getPrefix().size() > (*longestPrefix)->getPrefix().size())
+            {
+              longestPrefix = i;
+            }
         }
     }
   return longestPrefix;
diff --git a/tests/test-faces.cpp b/tests/test-faces.cpp
index 9fc5860..1fab695 100644
--- a/tests/test-faces.cpp
+++ b/tests/test-faces.cpp
@@ -19,6 +19,7 @@
     , timeoutCount(0)
     , regPrefixId(0)
     , inInterestCount(0)
+    , inInterestCount2(0)
     , regFailedCount(0)
   {
   }
@@ -44,6 +45,14 @@
   }
 
   void
+  onInterest2(Face& face)
+  {
+    ++inInterestCount2;
+
+    face.unsetInterestFilter(regPrefixId2);
+  }
+
+  void
   onRegFailed()
   {
     ++regFailedCount;
@@ -69,7 +78,9 @@
   uint32_t timeoutCount;
 
   const RegisteredPrefixId* regPrefixId;
+  const RegisteredPrefixId* regPrefixId2;
   uint32_t inInterestCount;
+  uint32_t inInterestCount2;
   uint32_t regFailedCount;
 };
 
@@ -144,6 +155,36 @@
   BOOST_CHECK_EQUAL(dataCount, 0);
 }
 
+BOOST_FIXTURE_TEST_CASE (SetTwoFilters, 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));
+  
+  regPrefixId2 = face.setInterestFilter("/Los/Angeles/Lakers",
+                                       bind(&FacesFixture::onInterest2, 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(inInterestCount2, 0);  
+  BOOST_CHECK_EQUAL(timeoutCount, 1);
+  BOOST_CHECK_EQUAL(dataCount, 0);
+}
+
 BOOST_AUTO_TEST_SUITE_END()
 
 } // namespace ndn