node: Implement prefix 'unreg' when interest filter is unset

Filter unsetting is useful in some applications that want to terminate
after data has been successfully pushed out to the forwarding daemon.

Change-Id: Iabada0db7d1bd653899941a294abd4c8cd20a80f
diff --git a/include/ndn-cpp/forwarding-entry.hpp b/include/ndn-cpp/forwarding-entry.hpp
index 662409a..e9a3f47 100644
--- a/include/ndn-cpp/forwarding-entry.hpp
+++ b/include/ndn-cpp/forwarding-entry.hpp
@@ -22,9 +22,9 @@
 public:    
   ForwardingEntry(const std::string& action,
                   const Name& prefix,
-                  int faceId,
-                  const ForwardingFlags& forwardingFlags,
-                  int freshnessPeriod) 
+                  int faceId = -1,
+                  const ForwardingFlags& forwardingFlags = ForwardingFlags(),
+                  int freshnessPeriod = -1) 
     : action_(action)
     , prefix_(prefix)
     , faceId_(faceId)
diff --git a/include/ndn-cpp/node.hpp b/include/ndn-cpp/node.hpp
index bbf89fd..b5e4e97 100644
--- a/include/ndn-cpp/node.hpp
+++ b/include/ndn-cpp/node.hpp
@@ -330,6 +330,8 @@
   PendingInterestTable pendingInterestTable_;
   RegisteredPrefixTable registeredPrefixTable_;
   Interest ndndIdFetcherInterest_;
+
+  int64_t faceId_; // internal face ID (needed for prefix de-registration)
   Buffer ndndId_;
 };
 
diff --git a/src/node.cpp b/src/node.cpp
index 5dcbd7b..404853e 100644
--- a/src/node.cpp
+++ b/src/node.cpp
@@ -122,10 +122,37 @@
 {
   // Go backwards through the list so we can erase entries.
   // Remove all entries even though pendingInterestId should be unique.
-  for (int i = (int)registeredPrefixTable_.size() - 1; i >= 0; --i) {
-    if (registeredPrefixTable_[i]->getRegisteredPrefixId() == registeredPrefixId)
-      registeredPrefixTable_.erase(registeredPrefixTable_.begin() + i);
-  }
+
+  for (RegisteredPrefixTable::iterator i = registeredPrefixTable_.begin();
+       i != registeredPrefixTable_.end();
+       ++i)
+    {
+      if ((*i)->getRegisteredPrefixId() == registeredPrefixId) {
+        ForwardingEntry forwardingEntry("unreg", *(*i)->getPrefix(), faceId_);
+        Data data;
+        data.setContent(forwardingEntry.wireEncode());
+        
+        SignatureSha256WithRsa signature;
+        signature.setValue(Block(Tlv::SignatureValue, ptr_lib::make_shared<Buffer>()));
+        data.setSignature(signature);
+
+        // Create an interest where the name has the encoded Data packet.
+        Name interestName;
+        interestName.append("ndnx");
+        interestName.append(ndndId_);
+        interestName.append("unreg");
+        interestName.append(data.wireEncode());
+
+        Interest interest(interestName);
+        interest.setScope(1);
+        interest.setInterestLifetime(1000);
+
+        expressInterest(interest, OnData(), OnTimeout());
+        
+        registeredPrefixTable_.erase(i);
+        break;
+      }
+    }
 }
 
 void 
@@ -208,7 +235,7 @@
         StatusResponse resp;
         resp.wireDecode(*val);
 
-        std::cerr << "StatusReponse: " << resp << std::endl;
+        // std::cerr << "StatusReponse: " << resp << std::endl;
       
         onRegisterFailed(prefix);
         return;
@@ -280,7 +307,8 @@
   }
 
   if (!pendingInterestTable_.empty()) {
-    // pitTimeoutCheckTimerActive = true;
+    pitTimeoutCheckTimerActive_ = true;
+    
     pitTimeoutCheckTimer_->expires_from_now(boost::posix_time::milliseconds(100));
     pitTimeoutCheckTimer_->async_wait(func_lib::bind(&Node::checkPitExpire, this));
   }
@@ -321,7 +349,14 @@
         const OnData onData = (*entry)->getOnData();
         const ptr_lib::shared_ptr<const Interest> interest = (*entry)->getInterest();
         pendingInterestTable_.erase(entry);
-        onData(interest, data);
+
+        if (onData) {
+          onData(interest, data);
+        }
+
+        if (pendingInterestTable_.empty()) {
+          pitTimeoutCheckTimer_->cancel(); // this will cause checkPitExpire invocation
+        }
       }
     }
 }
@@ -393,11 +428,7 @@
 Node::PendingInterest::callTimeout()
 {
   if (onTimeout_) {
-    // Ignore all exceptions.
-    try {
-      onTimeout_(interest_);
-    }
-    catch (...) { }
+    onTimeout_(interest_);
   }
 }